def construct_beta_quat_array(
    ebsd_map: ebsd.Map,
    alpha_phase_id: int = 0,
    variant_map: np.ndarray = None,
) -> np.ndarray:
    """Construct

    Parameters
    ----------
    ebsd_map:
        EBSD map to assign the beta variants for.
    alpha_phase_id
        Index of the alpha phase in the EBSD map.

    """
    if variant_map is None:
        variant_map = construct_variant_map(ebsd_map, alpha_phase_id)

    transformations = []
    for sym in unq_hex_syms:
        transformations.append(burg_trans * sym.conjugate)
    trans_comps = Quat.extract_quat_comps(transformations)
    trans_comps = trans_comps[:, variant_map[variant_map >= 0]]

    quat_comps = Quat.extract_quat_comps(ebsd_map.quatArray[variant_map >= 0])
    quat_comps_beta = np.empty_like(quat_comps)

    # transformations[variant] * quat
    quat_comps_beta[0, :] = (trans_comps[0, :] * quat_comps[0, :] -
                             trans_comps[1, :] * quat_comps[1, :] -
                             trans_comps[2, :] * quat_comps[2, :] -
                             trans_comps[3, :] * quat_comps[3, :])
    quat_comps_beta[1, :] = (trans_comps[1, :] * quat_comps[0, :] +
                             trans_comps[0, :] * quat_comps[1, :] -
                             trans_comps[3, :] * quat_comps[2, :] +
                             trans_comps[2, :] * quat_comps[3, :])
    quat_comps_beta[2, :] = (trans_comps[2, :] * quat_comps[0, :] +
                             trans_comps[0, :] * quat_comps[2, :] -
                             trans_comps[1, :] * quat_comps[3, :] +
                             trans_comps[3, :] * quat_comps[1, :])
    quat_comps_beta[3, :] = (trans_comps[3, :] * quat_comps[0, :] +
                             trans_comps[0, :] * quat_comps[3, :] -
                             trans_comps[2, :] * quat_comps[1, :] +
                             trans_comps[1, :] * quat_comps[2, :])
    # swap into positive hemisphere if required
    quat_comps_beta[:, quat_comps_beta[0, :] < 0] *= -1

    beta_quat_array = np.empty_like(ebsd_map.quatArray)
    beta_quat_array[variant_map < 0] = Quat(1, 0, 0, 0)
    for i, idx in enumerate(zip(*np.where(variant_map >= 0))):
        beta_quat_array[idx] = Quat(quat_comps_beta[:, i])

    return beta_quat_array
Esempio n. 2
0
def beta_oris() -> List[Quat]:
    """The 6 possible beta orientations for the `ori_single_valid` fixture."""
    return [
        Quat(0.11460994,  0.97057328,  0.10987647, -0.18105038),
        Quat(0.71894262,  0.52597293, -0.12611599,  0.43654181),
        Quat(0.4812518,   0.86403135, -0.00937589,  0.14750805),
        Quat(0.23608204, -0.12857975,  0.96217918,  0.04408791),
        Quat(0.39243229, -0.10727847, -0.59866151, -0.68999466),
        Quat(0.62851433, -0.23585823,  0.36351768, -0.64590675)
    ]
Esempio n. 3
0
    def test_calc(self):
        mock_map = Mock(spec=ebsd.Map)
        mock_map.quatArray = np.array([
            Quat([0.31666724, -0.91588522,  0.13405465, -0.20713635]),
            Quat([0.17612928, -0.20214505, -0.21599713, -0.93886159]),
            Quat([0.24967011, -0.224283,   -0.26045348, -0.90527673]),
            Quat([0.68070418, -0.53435491,  0.23619103, -0.44195072]),
            Quat([0.7293098,  -0.34952765, -0.07857021, -0.58289309]),
            Quat([0.00169551,  0.14777021,  0.12010977,  0.98169992]),
            Quat([0.47365417, -0.20536756, -0.20468846, -0.83161201]),
            Quat([0.78776179, -0.27972705,  0.09209514, -0.54101999]),
            Quat([0.33727506, -0.13311405, -0.13924545, -0.92148624]),
            Quat([0.41137644, -0.85164404,  0.21420115, -0.24411007]),
            Quat([0.26092708, -0.27640969, -0.29049792, -0.87813763]),
            Quat([0.51237664, -0.62480323, -0.16679851, -0.56503925])
        ]).reshape((3, 4))
        mock_map.shape = mock_map.quatArray.shape
        variant_map = np.array([[0,  3, -1,  1],
                                [2,  2,  4,  4],
                                [5, -1,  1,  2]])

        beta_quat_array = recon.construct_beta_quat_array(
            mock_map, variant_map=variant_map
        )
        expected_comps = [
            np.array([0.3586687,  -0.42249045, -0.28570384,  0.78181321]),
            np.array([0.04396812, -0.20834367, -0.45309011,  0.86566105]),
            np.array([1.,          0.,          0.,          0.]),
            np.array([0.13489744, -0.93982694,  0.30093181, -0.08926393]),
            np.array([0.66997125, -0.66745906,  0.24828395,  0.2097427]),
            np.array([0.46111146, -0.72030688, -0.25269131, -0.4524172]),
            np.array([0.31807292,  0.2294237,  -0.791435,    0.46885503]),
            np.array([0.1535714,  -0.26761921, -0.83850223,  0.44912114]),
            np.array([0.51219503,  0.6609771,  -0.31826009, -0.44662741]),
            np.array([1.,          0.,          0.,          0.]),
            np.array([0.26763438, -0.77098237, -0.48040495, -0.32119948]),
            np.array([0.56407948, -0.75208451, -0.06296879,  0.33498979])
        ]

        assert all([np.allclose(quat.quatCoef, row) for quat, row
                    in zip(beta_quat_array.flat, expected_comps)])
Esempio n. 4
0
def ori_quat_list_valid() -> List[Quat]:
    """A list of sample quaternion representing the orientations of grains."""
    return [
        Quat(0.22484510, 0.45464871, -0.70807342, 0.49129550),
        Quat(0.36520321, 0.25903472, -0.40342268, 0.79798357)
    ]
Esempio n. 5
0
def ori_single_valid_3() -> Quat:
    """A single sample quaternion representing the orientation of a grain."""
    return Quat(0.8730071, -0.41360125, -0.02295757, -0.25742097)
Esempio n. 6
0
def ori_single_valid_2() -> Quat:
    """A single sample quaternion representing the orientation of a grain."""
    return Quat(0.11939881, -0.36445855, -0.67237386, -0.63310922)
Esempio n. 7
0
def ori_single_valid() -> Quat:
    """A single sample quaternion representing the orientation of a grain."""
    return Quat(0.22484510, 0.45464871, -0.70807342, 0.49129550)
Esempio n. 8
0
    def calcNye(self):
        """
        Calculates Nye tensor and related GND density for the EBSD map.
        Stores result in self.Nye and self.GND.
        """
        self.buildQuatArray()
        print("\rFinding boundaries...", end="")
        syms = Quat.symEqv(self.crystalSym)
        numSyms = len(syms)

        # array to store quat components of initial and symmetric equivalents
        quatComps = np.empty((numSyms, 4, self.yDim, self.xDim))

        # populate with initial quat components
        for i, row in enumerate(self.quatArray):
            for j, quat in enumerate(row):
                quatComps[0, :, i, j] = quat.quatCoef

        # loop of over symmetries and apply to initial quat components
        # (excluding first symmetry as this is the identity transformation)
        for i, sym in enumerate(syms[1:], start=1):
            # sym[i] * quat for all points (* is quaternion product)
            quatComps[i, 0] = (quatComps[0, 0] * sym[0] - quatComps[0, 1] * sym[1] -
                               quatComps[0, 2] * sym[2] - quatComps[0, 3] * sym[3])
            quatComps[i, 1] = (quatComps[0, 0] * sym[1] + quatComps[0, 1] * sym[0] -
                               quatComps[0, 2] * sym[3] + quatComps[0, 3] * sym[2])
            quatComps[i, 2] = (quatComps[0, 0] * sym[2] + quatComps[0, 2] * sym[0] -
                               quatComps[0, 3] * sym[1] + quatComps[0, 1] * sym[3])
            quatComps[i, 3] = (quatComps[0, 0] * sym[3] + quatComps[0, 3] * sym[0] -
                               quatComps[0, 1] * sym[2] + quatComps[0, 2] * sym[1])

            # swap into positve hemisphere if required
            quatComps[i, :, quatComps[i, 0] < 0] *= -1

        # Arrays to store neigbour misorientation in positive x and y direction
        misOrix = np.zeros((numSyms, self.yDim, self.xDim))
        misOriy = np.zeros((numSyms, self.yDim, self.xDim))

        # loop over symmetries calculating misorientation to initial
        for i in range(numSyms):
            for j in range(self.xDim - 1):
                misOrix[i, :, j] = abs(np.einsum("ij,ij->j", quatComps[0, :, :, j], quatComps[i, :, :, j + 1]))

            for j in range(self.yDim - 1):
                misOriy[i, j, :] = abs(np.einsum("ij,ij->j", quatComps[0, :, j, :], quatComps[i, :, j + 1, :]))

        misOrix[misOrix > 1] = 1
        misOriy[misOriy > 1] = 1

        # find min misorientation (max here as misorientaion is cos of this)
        argmisOrix = np.argmax(misOrix, axis=0)
        argmisOriy = np.argmax(misOriy, axis=0)
        misOrix = np.max(misOrix, axis=0)
        misOriy = np.max(misOriy, axis=0)

        # convert to misorientation in degrees
        misOrix = 360 * np.arccos(misOrix) / np.pi
        misOriy = 360 * np.arccos(misOriy) / np.pi

        # calculate relative elastic distortion tensors at each point in the two directions
        betaderx = np.zeros((3, 3, self.yDim, self.xDim))
        betadery = betaderx
        for i in range(self.xDim - 1):
            for j in range(self.yDim - 1):
                q0x = Quat(quatComps[0, 0, j, i], quatComps[0, 1, j, i],
                           quatComps[0, 2, j, i], quatComps[0, 3, j, i])
                qix = Quat(quatComps[argmisOrix[j, i], 0, j, i + 1],
                           quatComps[argmisOrix[j, i], 1, j, i + 1],
                           quatComps[argmisOrix[j, i], 2, j, i + 1],
                           quatComps[argmisOrix[j, i], 3, j, i + 1])
                misoquatx = qix.conjugate * q0x
                # change stepsize to meters
                betaderx[:, :, j, i] = (Quat.rotMatrix(misoquatx) - np.eye(3)) / self.stepSize / 1e-6
                q0y = Quat(quatComps[0, 0, j, i], quatComps[0, 1, j, i],
                           quatComps[0, 2, j, i], quatComps[0, 3, j, i])
                qiy = Quat(quatComps[argmisOriy[j, i], 0, j + 1, i],
                           quatComps[argmisOriy[j, i], 1, j + 1, i],
                           quatComps[argmisOriy[j, i], 2, j + 1, i],
                           quatComps[argmisOriy[j, i], 3, j + 1, i])
                misoquaty = qiy.conjugate * q0y
                # change stepsize to meters
                betadery[:, :, j, i] = (Quat.rotMatrix(misoquaty) - np.eye(3)) / self.stepSize / 1e-6

        # Calculate the Nye Tensor
        alpha = np.empty((3, 3, self.yDim, self.xDim))
        bavg = 1.4e-10  # Burgers vector
        alpha[0, 2] = (betadery[0, 0] - betaderx[0, 1]) / bavg
        alpha[1, 2] = (betadery[1, 0] - betaderx[1, 1]) / bavg
        alpha[2, 2] = (betadery[2, 0] - betaderx[2, 1]) / bavg
        alpha[:, 1] = betaderx[:, 2] / bavg
        alpha[:, 0] = -1 * betadery[:, 2] / bavg

        # Calculate 3 possible L1 norms of Nye tensor for total
        # disloction density
        alpha_total3 = np.empty((self.yDim, self.xDim))
        alpha_total5 = np.empty((self.yDim, self.xDim))
        alpha_total9 = np.empty((self.yDim, self.xDim))
        alpha_total3 = 30 / 10. *(
                abs(alpha[0, 2]) + abs(alpha[1, 2]) +
                abs(alpha[2, 2])
        )
        alpha_total5 = 30 / 14. * (
                abs(alpha[0, 2]) + abs(alpha[1, 2]) + abs(alpha[2, 2]) +
                abs(alpha[1, 0]) + abs(alpha[0, 1])
        )
        alpha_total9 = 30 / 20. * (
                abs(alpha[0, 2]) + abs(alpha[1, 2]) + abs(alpha[2, 2]) +
                abs(alpha[0, 0]) + abs(alpha[1, 0]) + abs(alpha[2, 0]) +
                abs(alpha[0, 1]) + abs(alpha[1, 1]) + abs(alpha[2, 1])
        )
        alpha_total3[abs(alpha_total3) < 1] = 1e12
        alpha_total5[abs(alpha_total3) < 1] = 1e12
        alpha_total9[abs(alpha_total3) < 1] = 1e12

        # choose from the different alpha_totals according to preference;
        # see Ruggles GND density paper
        self.GND = alpha_total9
        self.Nye = alpha