def quatAverageCluster(q_in, qsym): """ """ from symmetry import toFundamentalRegion assert q_in.ndim == 2, "input must be 2-s hstacked quats" # renormalize q_in = unitVector(q_in) # check to see num of quats is > 1 if q_in.shape[1] < 3: if q_in.shape[1] == 1: q_bar = q_in else: ma, mq = misorientation(q_in[:, 0].reshape(4, 1), q_in[:, 1].reshape(4, 1), (qsym,)) q_bar = quatProduct(q_in[:, 0].reshape(4, 1), quatOfExpMap(0.5 * ma * unitVector(mq[1:].reshape(3, 1)))) else: # use first quat as initial guess phi = 2.0 * arccos(q_in[0, 0]) if phi <= finfo(float).eps: x0 = zeros(3) else: n = unitVector(q_in[1:, 0].reshape(3, 1)) x0 = phi * n.flatten() # first drag to origin using first quat (arb!) q0 = q_in[:, 0].reshape(4, 1) qrot = dot(quatProductMatrix(invertQuat(q0), mult="right"), q_in) # second, re-cast to FR qrot = toFundamentalRegion(qrot.squeeze(), crysSym=qsym) # compute arithmetic average q_bar = unitVector(average(qrot, axis=1).reshape(4, 1)) # unrotate! q_bar = dot(quatProductMatrix(q0, mult="right"), q_bar) # re-map q_bar = toFundamentalRegion(q_bar, crysSym=qsym) return q_bar
def quatAverageCluster(q_in, qsym): """ """ from symmetry import toFundamentalRegion assert q_in.ndim == 2, 'input must be 2-s hstacked quats' # renormalize q_in = unitVector(q_in) # check to see num of quats is > 1 if q_in.shape[1] < 3: if q_in.shape[1] == 1: q_bar = q_in else: ma, mq = misorientation(q_in[:, 0].reshape(4, 1), q_in[:, 1].reshape(4, 1), (qsym,)) q_bar = quatProduct( q_in[:, 0].reshape(4, 1), quatOfExpMap(0.5*ma*unitVector(mq[1:].reshape(3, 1))) ) else: # first drag to origin using first quat (arb!) q0 = q_in[:, 0].reshape(4, 1) qrot = dot( quatProductMatrix(invertQuat(q0), mult='left'), q_in) # second, re-cast to FR qrot = toFundamentalRegion(qrot.squeeze(), crysSym=qsym) # compute arithmetic average q_bar = unitVector(average(qrot, axis=1).reshape(4, 1)) # unrotate! q_bar = dot( quatProductMatrix(q0, mult='left'), q_bar) # re-map q_bar = toFundamentalRegion(q_bar, crysSym=qsym) return q_bar
def quatAverageCluster(q_in, qsym): """ """ from symmetry import toFundamentalRegion assert q_in.ndim == 2, 'input must be 2-s hstacked quats' # renormalize q_in = unitVector(q_in) # check to see num of quats is > 1 if q_in.shape[1] < 3: if q_in.shape[1] == 1: q_bar = q_in else: ma, mq = misorientation(q_in[:, 0].reshape(4, 1), q_in[:, 1].reshape(4, 1), (qsym,)) q_bar = quatProduct(q_in[:, 0].reshape(4, 1), quatOfExpMap(0.5*ma*unitVector(mq[1:].reshape(3, 1)))) else: # first drag to origin using first quat (arb!) q0 = q_in[:, 0].reshape(4, 1) qrot = dot( quatProductMatrix( invertQuat( q0 ), mult='left' ), q_in) # second, re-cast to FR qrot = toFundamentalRegion(qrot.squeeze(), crysSym=qsym) # compute arithmetic average q_bar = unitVector(average(qrot, axis=1).reshape(4, 1)) # unrotate! q_bar = dot( quatProductMatrix( q0, mult='left' ), q_bar) # re-map q_bar = toFundamentalRegion(q_bar, crysSym=qsym) return q_bar
def discreteFiber(c, s, B=I3, ndiv=120, invert=False, csym=None, ssym=None): """ """ import symmetry as S ztol = 1.e-8 # arg handling for c if hasattr(c, '__len__'): if hasattr(c, 'shape'): assert c.shape[0] == 3, \ 'scattering vector must be 3-d; yours is %d-d' \ % (c.shape[0]) if len(c.shape) == 1: c = c.reshape(3, 1) elif len(c.shape) > 2: raise RuntimeError, \ 'incorrect arg shape; must be 1-d or 2-d, yours is %d-d' \ % (len(c.shape)) else: # convert list input to array and transpose if len(c) == 3 and isscalar(c[0]): c = asarray(c).reshape(3, 1) else: c = asarray(c).T else: raise RuntimeError, 'input must be array-like' # arg handling for s if hasattr(s, '__len__'): if hasattr(s, 'shape'): assert s.shape[0] == 3, \ 'scattering vector must be 3-d; yours is %d-d' \ % (s.shape[0]) if len(s.shape) == 1: s = s.reshape(3, 1) elif len(s.shape) > 2: raise RuntimeError, \ 'incorrect arg shape; must be 1-d or 2-d, yours is %d-d' \ % (len(s.shape)) else: # convert list input to array and transpose if len(s) == 3 and isscalar(s[0]): s = asarray(s).reshape(3, 1) else: s = asarray(s).T else: raise RuntimeError, 'input must be array-like' nptc = c.shape[1] npts = s.shape[1] c = unitVector(dot(B, c)) # turn c hkls into unit vector in crys frame s = unitVector(s) # convert s to unit vector in samp frame retval = [] for i_c in range(nptc): dupl_c = tile(c[:, i_c], (npts, 1)).T ax = s + dupl_c anrm = columnNorm(ax).squeeze() # should be 1-d okay = anrm > ztol nokay = okay.sum() if nokay == npts: ax = ax / tile(anrm, (3, 1)) else: nspace = nullSpace(c[:, i_c].reshape(3, 1)) hperp = nspace[:, 0].reshape(3, 1) if nokay == 0: ax = tile(hperp, (1, npts)) else: ax[:, okay] = ax[:, okay] / tile(anrm[okay], (3, 1)) ax[:, not okay] = tile(hperp, (1, npts - nokay)) q0 = vstack( [ zeros(npts), ax ] ) # find rotations # note: the following line fixes bug with use of arange with float increments phi = arange(0, ndiv) * (2*pi/float(ndiv)) qh = quatOfAngleAxis(phi, tile(c[:, i_c], (ndiv, 1)).T) # the fibers, arraged as (npts, 4, ndiv) qfib = dot( quatProductMatrix(qh, mult='right'), q0 ).transpose(2, 1, 0) if csym is not None: retval.append(S.toFundamentalRegion(qfib.squeeze(), crysSym=csym, sampSym=ssym)) else: retval.append(fixQuat(qfib).squeeze()) return retval
def discreteFiber(c, s, B=I3, ndiv=120, invert=False, csym=None, ssym=None): """ """ import symmetry as S ztol = 1.e-8 # arg handling for c if hasattr(c, '__len__'): if hasattr(c, 'shape'): assert c.shape[0] == 3, \ 'scattering vector must be 3-d; yours is %d-d' \ % (c.shape[0]) if len(c.shape) == 1: c = c.reshape(3, 1) elif len(c.shape) > 2: raise RuntimeError, \ 'incorrect arg shape; must be 1-d or 2-d, yours is %d-d' \ % (len(c.shape)) else: # convert list input to array and transpose if len(c) == 3 and isscalar(c[0]): c = asarray(c).reshape(3, 1) else: c = asarray(c).T else: raise RuntimeError, 'input must be array-like' # arg handling for s if hasattr(s, '__len__'): if hasattr(s, 'shape'): assert s.shape[0] == 3, \ 'scattering vector must be 3-d; yours is %d-d' \ % (s.shape[0]) if len(s.shape) == 1: s = s.reshape(3, 1) elif len(s.shape) > 2: raise RuntimeError, \ 'incorrect arg shape; must be 1-d or 2-d, yours is %d-d' \ % (len(s.shape)) else: # convert list input to array and transpose if len(s) == 3 and isscalar(s[0]): s = asarray(s).reshape(3, 1) else: s = asarray(s).T else: raise RuntimeError, 'input must be array-like' nptc = c.shape[1] npts = s.shape[1] c = unitVector(dot(B, c)) # turn c hkls into unit vector in crys frame s = unitVector(s) # convert s to unit vector in samp frame retval = [] for i_c in range(nptc): dupl_c = tile(c[:, i_c], (npts, 1)).T ax = s + dupl_c anrm = columnNorm(ax).squeeze() # should be 1-d okay = anrm > ztol nokay = okay.sum() if nokay == npts: ax = ax / tile(anrm, (3, 1)) else: nspace = nullSpace(c[:, i_c].reshape(3, 1)) hperp = nspace[:, 0].reshape(3, 1) if nokay == 0: ax = tile(hperp, (1, npts)) else: ax[:, okay] = ax[:, okay] / tile(anrm[okay], (3, 1)) ax[:, not okay] = tile(hperp, (1, npts - nokay)) q0 = vstack([zeros(npts), ax]) # find rotations # note: the following line fixes bug with use of arange with float increments phi = arange(0, ndiv) * (2 * pi / float(ndiv)) qh = quatOfAngleAxis(phi, tile(c[:, i_c], (ndiv, 1)).T) # the fibers, arraged as (npts, 4, ndiv) qfib = dot(quatProductMatrix(qh, mult='right'), q0).transpose(2, 1, 0) if csym is not None: retval.append( S.toFundamentalRegion(qfib.squeeze(), crysSym=csym, sampSym=ssym)) else: retval.append(fixQuat(qfib).squeeze()) return retval