Beispiel #1
0
def misorientationStats(misorient, *wts):
    '''
    MisorientationStats - Misorientation correlation statistics.

      USAGE:

      stats = MisorientationStats(misorient, locations)
      stats = MisorientationStats(misorient, locations, wts)

      INPUT:

      misorient is 4 x n, 
                a list of misorientation quaternions,
                assumed to have been derived from properly clustered 
                orientation data
      wts       is 1 x n, (optional)
                a list of weights; if not specified, uniform weights are used

      OUTPUT:

      stats is a structure with five components:

            W     is a 3 x 3 matrix (A in Barton paper)
            Winv  is a 3 x 3 matrix (A^-1 in Barton paper)
            wi    is 3 x n, the unnormalized axial vectors

      REFERENCE:  

      "A Methodology for Determining Average Lattice Orientation and 
      Its Application to the  Characterization of Grain Substructure",

      Nathan R. Barton and Paul R. Dawson,

      Metallurgical and Materials Transactions A,
      Volume 32A, August 2001, pp. 1967--1975
  

    '''
    misorient = utl.mat2d_row_order(misorient)
    d, n = misorient.shape
    if len(wts) == 0:
        wts = np.tile(1.0 / n, (3, n))
    else:
        wts = np.tile(wts, (3, 1))

    wts1 = np.tile(wts[0, :], (4, 1))
    misOriCen = sph.SphereAverage(misorient, **{'wts': wts1})
    misorient = misorient - np.tile(misOriCen, (1, n))

    ang = utl.mat2d_row_order(2 * np.arccos(misorient[0, :]))
    wsc = np.zeros(ang.shape)

    limit = (ang < np.finfo(float).eps)
    nlimit = (ang > np.finfo(float).eps)

    angn = ang[nlimit]

    wsc[nlimit] = angn / np.sin(angn / 2)
    wsc[limit] = 2

    wi = misorient[1:4, :] * np.tile(wsc.T, (3, 1))

    angax = np.zeros((4, n))
    angax[0, :] = np.linalg.norm(wi, axis=0)
    angax[1:4, :] = normalize(wi, axis=0)

    Winv = np.sum(utl.RankOneMatrix(wi * wts, wi), axis=2)

    #We needed to scale this up if it was close to being ill-conditioned
    if (np.abs(np.linalg.det(Winv)) < 1e-6):
        if (np.abs(np.linalg.det(Winv)) < 1e-16):
            W = np.zeros((3, 3))
        else:
            Wtemp = np.multiply(1e9, Winv)
            W = np.multiply(1e9, np.linalg.inv(Wtemp))
    else:
        W = np.linalg.inv(Winv)

    stat = {'W': W, 'Winv': Winv, 'wi': wi, 'angaxis': angax}

    return stat
Beispiel #2
0
def bartonStats(misorient, locations, *wts):
    '''
    MisorientationStats - Misorientation correlation statistics.

      USAGE:

      stats = MisorientationStats(misorient, locations)
      stats = MisorientationStats(misorient, locations, wts)

      INPUT:

      misorient is 4 x n, 
                a list of misorientation quaternions,
                assumed to have been derived from properly clustered 
                orientation data
      locations is d x n, (d <= 3) 
                a list of spatial locations corresponding to the 
                misorientations
      wts       is 1 x n, (optional)
                a list of weights; if not specified, uniform weights are used

      OUTPUT:

      stats is a structure with five components:

            W     is a 3 x 3 matrix (A in Barton paper)
            X     is a d x d matrix (M in Barton paper)
            WX    is a 3 x d matrix (cross-correlation
                       of normalized variables; X in
                       Barton paper)
            wi    is 3 x n, the unnormalized axial vectors
            xi    is d x n, the unnormalized spatial directions
                            from the centroid

      REFERENCE:  

      "A Methodology for Determining Average Lattice Orientation and 
      Its Application to the  Characterization of Grain Substructure",

      Nathan R. Barton and Paul R. Dawson,

      Metallurgical and Materials Transactions A,
      Volume 32A, August 2001, pp. 1967--1975
  

    '''
    locations = utl.mat2d_row_order(locations)
    misorient = utl.mat2d_row_order(misorient)
    d, n = misorient.shape
    if len(wts) == 0:
        wts = np.tile(1.0 / n, (3, n))
    else:
        wts = np.tile(wts, (3, 1))

    wts1 = np.tile(wts[0, :], (4, 1))
    misOriCen = sph.SphereAverage(misorient, **{'wts': wts1})
    misorient = misorient - np.tile(misOriCen, (1, n))

    ang = utl.mat2d_row_order(2 * np.arccos(misorient[0, :]))
    wsc = np.zeros(ang.shape)

    limit = (ang < np.finfo(float).eps)
    nlimit = (ang > np.finfo(float).eps)

    angn = ang[nlimit]

    wsc[nlimit] = angn / np.sin(angn / 2)
    wsc[limit] = 2

    wi = misorient[1:4, :] * np.tile(wsc.T, (3, 1))

    wi = wi * np.tile(ang.T, (3, 1))

    cen = utl.mat2d_row_order(np.sum(locations * wts, axis=1))

    xi = locations - np.tile(cen, (1, n))

    Winv = np.sum(utl.RankOneMatrix(wi * wts, wi), axis=2)
    Xinv = np.sum(utl.RankOneMatrix(xi * wts, xi), axis=2)
    #We needed to scale this up if it was close to being ill-conditioned
    if (np.abs(np.linalg.det(Winv)) < 1e-6):
        if (np.abs(np.linalg.det(Winv)) < 1e-16):
            W = np.zeros((3, 3))
        else:
            Wtemp = np.multiply(1e9, Winv)
            W = np.multiply(1e9, np.linalg.inv(Wtemp))
    else:
        W = np.linalg.inv(Winv)
    Whalf = sci.linalg.sqrtm(W)

    if (np.abs(np.linalg.det(Xinv)) < 1e-6):
        Xtemp = np.multiply(1e9, Xinv)
        X = np.multiply(1e9, np.linalg.inv(Xtemp))
    else:
        X = np.linalg.inv(Xinv)
    Xhalf = sci.linalg.sqrtm(X)

    wibar = np.dot(Whalf, wi)
    xibar = np.dot(Xhalf, xi)

    WX = np.sum(utl.RankOneMatrix(wibar * wts, xibar), axis=2)

    stat = {
        'W': W,
        'Winv': Winv,
        'Xinv': Xinv,
        'X': X,
        'WX': WX,
        'wi': wi,
        'xi': xi
    }

    return stat