def convertUToRotMat(Urows, U0, symTag='Oh', display=False): """ Takes GrainSpotter gff ouput in rows U11 U12 U13 U21 U22 U23 U13 U23 U33 and takes it into the hexrd/APS frame of reference Urows comes from grainspotter's gff output U0 comes from xrd.crystallography.latticeVectors.U0 """ numU, testDim = Urows.shape assert testDim == 9, "Your input must have 9 columns; yours has %d" % (testDim) qin = quatOfRotMat(Urows.reshape(numU, 3, 3)) qout = num.dot( quatProductMatrix( quatOfRotMat(fableSampCOB), mult='left' ), \ num.dot( quatProductMatrix( quatOfRotMat(U0.T), mult='right'), \ qin ).squeeze() ).squeeze() if qout.ndim == 1: qout = toFundamentalRegion(qout.reshape(4, 1), crysSym=symTag, sampSym=None) else: qout = toFundamentalRegion(qout, crysSym=symTag, sampSym=None) if display: print "quaternions in (Fable convention):" print qin.T print "quaternions out (hexrd convention, symmetrically reduced)" print qout.T pass Uout = rotMatOfQuat(qout) return Uout
def convertRotMatToFableU(rMats, U0=num.eye(3), symTag='Oh', display=False): """ Makes GrainSpotter gff ouput U11 U12 U13 U21 U22 U23 U13 U23 U33 and takes it into the hexrd/APS frame of reference Urows comes from grainspotter's gff output U0 comes from xrd.crystallography.latticeVectors.U0 """ numU = num.shape(num.atleast_3d(rMats))[0] qin = quatOfRotMat(num.atleast_3d(rMats)) qout = num.dot( quatProductMatrix( quatOfRotMat(fableSampCOB.T), mult='left' ), \ num.dot( quatProductMatrix( quatOfRotMat(U0), mult='right'), \ qin ).squeeze() ).squeeze() if qout.ndim == 1: qout = toFundamentalRegion(qout.reshape(4, 1), crysSym=symTag, sampSym=None) else: qout = toFundamentalRegion(qout, crysSym=symTag, sampSym=None) if display: print "quaternions in (hexrd convention):" print qin.T print "quaternions out (Fable convention, symmetrically reduced)" print qout.T pass Uout = rotMatOfQuat(qout) return Uout
def convertUToRotMat(Urows, U0, symTag='Oh', display=False): """ Takes GrainSpotter gff ouput in rows U11 U12 U13 U21 U22 U23 U13 U23 U33 and takes it into the hexrd/APS frame of reference Urows comes from grainspotter's gff output U0 comes from xrd.crystallography.latticeVectors.U0 """ numU, testDim = Urows.shape assert testDim == 9, "Your input must have 9 columns; yours has %d" % ( testDim) qin = quatOfRotMat(Urows.reshape(numU, 3, 3)) qout = num.dot( quatProductMatrix( quatOfRotMat(fableSampCOB), mult='left' ), \ num.dot( quatProductMatrix( quatOfRotMat(U0.T), mult='right'), \ qin ).squeeze() ).squeeze() if qout.ndim == 1: qout = toFundamentalRegion(qout.reshape(4, 1), crysSym=symTag, sampSym=None) else: qout = toFundamentalRegion(qout, crysSym=symTag, sampSym=None) if display: print "quaternions in (Fable convention):" print qin.T print "quaternions out (hexrd convention, symmetrically reduced)" print qout.T pass Uout = rotMatOfQuat(qout) return Uout
def convertRotMatToRisoeU(rMats, U0, symTag='Oh'): """ Makes GrainSpotter gff ouput U11 U12 U13 U21 U22 U23 U13 U23 U33 and takes it into the LLNL/APS frame of reference Urows comes from grainspotter's gff output U0 comes from xrd.crystallography.latticeVectors.U0 """ R = hexrd.xrd.rotations # formerly import numU = num.shape(num.atleast_3d(rMats))[0] Rsamp = num.dot( R.rotMatOfExpMap(piby2*Zl), R.rotMatOfExpMap(piby2*Yl) ) qin = R.quatOfRotMat(num.atleast_3d(rMats)) print "quaternions in (LLNL convention):" print qin.T qout = num.dot( R.quatProductMatrix( R.quatOfRotMat(Rsamp.T), mult='left' ), \ num.dot( R.quatProductMatrix( R.quatOfRotMat(U0), mult='right'), \ qin ).squeeze() ).squeeze() if qout.ndim == 1: qout = toFundamentalRegion(qout.reshape(4, 1), crysSym=symTag, sampSym=None) else: qout = toFundamentalRegion(qout, crysSym=symTag, sampSym=None) print "quaternions out (Risoe convention, symmetrically reduced)" print qout.T Uout = R.rotMatOfQuat(qout) return Uout
def convertUToRotMat(Urows, U0, symTag='Oh'): """ Takes GrainSpotter gff ouput U11 U12 U13 U21 U22 U23 U13 U23 U33 and takes it into the LLNL/APS frame of reference Urows comes from grainspotter's gff output U0 comes from xrd.crystallography.latticeVectors.U0 """ R = hexrd.xrd.rotations numU, testDim = Urows.shape assert testDim == 9, "Your input must have 9 columns; yours has %d" % (testDim) Rsamp = num.dot( R.rotMatOfExpMap(piby2*Zl), R.rotMatOfExpMap(piby2*Yl) ) qin = R.quatOfRotMat(Urows.reshape(numU, 3, 3)) print "quaternions in (Risoe convention):" print qin.T qout = num.dot( R.quatProductMatrix( R.quatOfRotMat(Rsamp), mult='left' ), \ num.dot( R.quatProductMatrix( R.quatOfRotMat(U0.T), mult='right'), \ qin ).squeeze() ).squeeze() if qout.ndim == 1: qout = toFundamentalRegion(qout.reshape(4, 1), crysSym=symTag, sampSym=None) else: qout = toFundamentalRegion(qout, crysSym=symTag, sampSym=None) print "quaternions out (LLNL convention, symmetrically reduced)" print qout.T Uout = R.rotMatOfQuat(qout) return Uout
def remove_duplicate_grains(grain_data, qsyms, dist_thresh=0.01, misorient_thresh=0.1, comp_diff=0.1): total_grains = grain_data.shape[0] all_comp = grain_data[:, 1] grain_quats = rot.quatOfExpMap(grain_data[:, 3:6].T) dup_list = np.array([]) print 'Removing duplicate grains' for i in np.arange(total_grains - 1): cur_pos = grain_data[i, 3:6] other_pos = grain_data[(i + 1):, 3:6] xdist = cur_pos[0] - other_pos[:, 0] ydist = cur_pos[1] - other_pos[:, 1] zdist = cur_pos[2] - other_pos[:, 2] dist = np.sqrt(xdist**2. + ydist**2. + zdist**2.) if np.min(dist) < dist_thresh: q1 = sym.toFundamentalRegion(np.atleast_2d(grain_quats[:, i]).T, crysSym=qsyms) q2 = sym.toFundamentalRegion(np.atleast_2d( grain_quats[:, np.argmin(dist) + i + 1]).T, crysSym=qsyms) misorientation = rot.misorientation(q1, q2)[0] * 180. / np.pi if misorientation < misorient_thresh: dup_list = np.append(dup_list, np.argmin(dist) + i + 1) if (np.abs(all_comp[i] - all_comp[np.argmin(dist) + i + 1]) <= comp_diff): grain_data[ i, :] = (grain_data[i, :] + grain_data[np.argmin(dist) + i + 1, :]) / 2. elif ((all_comp[np.argmin(dist) + i + 1] - all_comp[i]) > 0): grain_data[i, :] = grain_data[np.argmin(dist) + i + 1, :] grain_data = np.delete(grain_data, dup_list, axis=0) print 'Removed %d Grains' % (len(dup_list)) grain_data[:, 0] = np.arange(grain_data.shape[0]) return grain_data, dup_list
def _compute_centroids_dense(cl, qfib_r, qsym): """compute centroids when clusters are compact""" if np.any(cl == -1): nblobs = len(np.unique(cl)) - 1 else: nblobs = len(np.unique(cl)) qbar = np.zeros((4, nblobs)) for i in range(nblobs): cluster_indices = (cl == i + 1) this_cluster = qfib_r[:, cluster_indices] qbar[:, i] = np.average(np.atleast_2d(this_cluster), axis=1) qbar = sym.toFundamentalRegion(mutil.unitVector(qbar), crysSym=qsym) return np.atleast_2d(qbar)
def remove_duplicate_grains(grain_data,qsyms,dist_thresh=0.01,misorient_thresh=0.1,comp_diff=0.1): total_grains=grain_data.shape[0] all_comp=grain_data[:,1] grain_quats=rot.quatOfExpMap(grain_data[:,3:6].T) dup_list=np.array([]) print 'Removing duplicate grains' for i in np.arange(total_grains-1): cur_pos=grain_data[i,3:6] other_pos=grain_data[(i+1):,3:6] xdist=cur_pos[0]-other_pos[:,0] ydist=cur_pos[1]-other_pos[:,1] zdist=cur_pos[2]-other_pos[:,2] dist=np.sqrt(xdist**2.+ydist**2.+zdist**2.) if np.min(dist)<dist_thresh: q1=sym.toFundamentalRegion(np.atleast_2d(grain_quats[:,i]).T,crysSym=qsyms) q2=sym.toFundamentalRegion(np.atleast_2d(grain_quats[:,np.argmin(dist)+i+1]).T,crysSym=qsyms) misorientation=rot.misorientation(q1,q2)[0]*180./np.pi if misorientation < misorient_thresh: dup_list=np.append(dup_list,np.argmin(dist)+i+1) if (np.abs(all_comp[i] - all_comp[np.argmin(dist)+i+1]) <=comp_diff): grain_data[i,:]=(grain_data[i,:]+grain_data[np.argmin(dist)+i+1,:])/2. elif ( (all_comp[np.argmin(dist)+i+1]-all_comp[i]) >0): grain_data[i,:]=grain_data[np.argmin(dist)+i+1,:] grain_data=np.delete(grain_data,dup_list,axis=0) print 'Removed %d Grains' % (len(dup_list)) grain_data[:,0]=np.arange(grain_data.shape[0]) return grain_data,dup_list
def run_cluster(compl, qfib, qsym, cfg, min_samples=None, compl_thresh=None, radius=None): """ """ algorithm = cfg.find_orientations.clustering.algorithm cl_radius = cfg.find_orientations.clustering.radius min_compl = cfg.find_orientations.clustering.completeness # check for override on completeness threshold if compl_thresh is not None: min_compl = compl_thresh # check for override on radius if radius is not None: cl_radius = radius start = time.clock() # time this num_above = sum(np.array(compl) > min_compl) if num_above == 0: # nothing to cluster qbar = cl = np.array([]) elif num_above == 1: # short circuit qbar = qfib[:, np.array(compl) > min_compl] cl = [1] else: # use compiled module for distance # just to be safe, must order qsym as C-contiguous qsym = np.array(qsym.T, order='C').T def quat_distance(x, y): return xfcapi.quat_distance(np.array(x, order='C'), np.array(y, order='C'), qsym) qfib_r = qfib[:, np.array(compl) > min_compl] num_ors = qfib_r.shape[1] if num_ors > 25000: if algorithm == 'sph-dbscan' or algorithm == 'fclusterdata': logger.info("defaulting to orthographic DBSCAN") algorithm = 'ort-dbscan' #raise RuntimeError, \ # "Requested clustering of %d orientations, which would be too slow!" %qfib_r.shape[1] logger.info( "Feeding %d orientations above %.1f%% to clustering", num_ors, 100*min_compl ) if algorithm == 'dbscan' and not have_sklearn: algorithm = 'fclusterdata' logger.warning( "sklearn >= 0.14 required for dbscan; using fclusterdata" ) if algorithm == 'dbscan' or algorithm == 'ort-dbscan' or algorithm == 'sph-dbscan': # munge min_samples according to options if min_samples is None or cfg.find_orientations.use_quaternion_grid is not None: min_samples = 1 if algorithm == 'sph-dbscan': # compute distance matrix pdist = pairwise_distances( qfib_r.T, metric=quat_distance, n_jobs=1 ) # run dbscan core_samples, labels = dbscan( pdist, eps=np.radians(cl_radius), min_samples=min_samples, metric='precomputed' ) else: if algorithm == 'ort-dbscan': pts = qfib_r[1:, :].T else: pts = qfib_r.T # run dbscan core_samples, labels = dbscan( pts, eps=0.5*np.radians(cl_radius), min_samples=min_samples, metric='minkowski', p=2, ) # extract cluster labels cl = np.array(labels, dtype=int) # convert to array noise_points = cl == -1 # index for marking noise cl += 1 # move index to 1-based instead of 0 cl[noise_points] = -1 # re-mark noise as -1 logger.info("dbscan found %d noise points", sum(noise_points)) elif algorithm == 'fclusterdata': cl = cluster.hierarchy.fclusterdata( qfib_r.T, np.radians(cl_radius), criterion='distance', metric=quat_distance ) else: raise RuntimeError( "Clustering algorithm %s not recognized" % algorithm ) # extract number of clusters if np.any(cl == -1): nblobs = len(np.unique(cl)) - 1 else: nblobs = len(np.unique(cl)) #import pdb; pdb.set_trace() """ PERFORM AVERAGING TO GET CLUSTER CENTROIDS """ qbar = np.zeros((4, nblobs)) if algorithm == 'sph-dbscan' or algorithm == 'fclusterdata': # here clusters can be split across fr for i in range(nblobs): npts = sum(cl == i + 1) qbar[:, i] = rot.quatAverageCluster( qfib_r[:, cl == i + 1].reshape(4, npts), qsym ).flatten() pass else: # here clusters are ompact by construction for i in range(nblobs): qbar[:, i] = np.average(np.atleast_2d(qfib_r[:, cl == i + 1]), axis=1) pass qbar = sym.toFundamentalRegion(mutil.unitVector(qbar), crysSym=qsym) logger.info("clustering took %f seconds", time.clock() - start) logger.info( "Found %d orientation clusters with >=%.1f%% completeness" " and %2f misorientation", qbar.size/4, 100.*min_compl, cl_radius ) return np.atleast_2d(qbar), cl