Beispiel #1
1
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
Beispiel #2
0
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
Beispiel #3
0
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
Beispiel #4
0
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
Beispiel #5
0
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
Beispiel #6
0
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
Beispiel #7
0
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
Beispiel #8
0
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)
Beispiel #9
0
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
Beispiel #10
0
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