Пример #1
0
def rotMatOfExpMap_orig(expMap):
    """
    Original rotMatOfExpMap, used for comparison to optimized version
    """
    if isinstance(expMap, ndarray):
        if expMap.ndim != 2:
            if expMap.ndim == 1 and len(expMap) == 3:
                numObjs = 1
                expMap = expMap.reshape(3, 1)
            else:
                raise RuntimeError("input is the wrong dimensionality")
        elif expMap.shape[0] != 3:
            raise RuntimeError(
                "input is the wrong shape along the 0-axis; "
                + "Yours is %d when is should be 3"
                % (expMap.shape[0])
            )
        else:
            numObjs = expMap.shape[1]
    elif isinstance(expMap, list) or isinstance(expMap, tuple):
        if len(expMap) != 3:
            raise RuntimeError(
                "for list/tuple input only one exponential map "
                + "vector is allowed"
            )
        else:
            if not isscalar(expMap[0]) or not isscalar(expMap[1]) \
              or not isscalar(expMap[2]):
                raise RuntimeError(
                    "for list/tuple input only one exponential map "
                    + "vector is allowed"
                )
            else:
                numObjs = 1
                expMap = asarray(expMap).reshape(3, 1)

    phi = columnNorm(expMap)  # angles of rotation from exponential maps
    W = skewMatrixOfVector(expMap)  # skew matrices of exponential maps

    # Find tiny angles to avoid divide-by-zero and apply limits in expressions
    zeroIndex = phi < cnst.epsf
    phi[zeroIndex] = 1

    # first term
    C1 = sin(phi) / phi
    C1[zeroIndex] = 1

    # second term
    C2 = (1 - cos(phi)) / phi**2
    C2[zeroIndex] = 1

    if numObjs == 1:
        rmat = I3 + C1 * W + C2 * dot(W, W)
    else:
        rmat = zeros((numObjs, 3, 3))
        for i in range(numObjs):
            rmat[i, :, :] = \
                I3 + C1[i] * W[i, :, :] + C2[i] * dot(W[i, :, :], W[i, :, :])

    return rmat
def contained_in_sst(vectors, vertices_ccw):
    """
    checks hstack array of unit vectors

    !!! inputs must both be unit vectors
    !!! vertices must be CCW
    """
    # column-wise normals to the spherical triangle edges
    sst_normals = np.array([
        np.cross(vertices_ccw[:, i[0]], vertices_ccw[:, i[1]])
        for i in [(0, 1), (1, 2), (2, 0)]
    ]).T
    sst_normals_unit = mutil.unitVector(sst_normals)

    angles = np.arcsin(mutil.columnNorm(sst_normals))
    edges = []
    for i, ang in enumerate(angles):
        sub_ang = np.linspace(0, ang, endpoint=True)
        for j in sub_ang:
            rm = rot.rotMatOfExpMap(j * sst_normals_unit[:, i].reshape(3, 1))
            edges.append(np.dot(vertices_ccw[:, i], rm.T))
        edges.append(np.nan * np.ones(3))

    dim, n = vectors.shape
    contained = []
    for v in vectors.T:
        d0 = np.dot(sst_normals_unit[:, 0], v)
        d1 = np.dot(sst_normals_unit[:, 1], v)
        d2 = np.dot(sst_normals_unit[:, 2], v)
        contained.append(np.all([d0 > 0, d1 > 0, d2 > 0]))
    return contained, np.vstack(edges)
Пример #3
0
def quatOfExpMap(expMap):
    """
    """
    angles = columnNorm(expMap)
    axes   = unitVector(expMap)

    quats = quatOfAngleAxis(angles, axes)
    return quats
Пример #4
0
def quatOfExpMap(expMap):
    """
    """
    angles = columnNorm(expMap)
    axes = unitVector(expMap)

    quats = quatOfAngleAxis(angles, axes)
    return quats
Пример #5
0
def rotMatOfExpMap_opt(expMap):
    """Optimized version of rotMatOfExpMap
    """
    if expMap.ndim == 1:
        expMap = expMap.reshape(3, 1)

    # angles of rotation from exponential maps
    phi = atleast_1d(columnNorm(expMap))

    # skew matrices of exponential maps
    W = skewMatrixOfVector(expMap)

    # Find tiny angles to avoid divide-by-zero and apply limits in expressions
    zeroIndex = phi < cnst.epsf
    phi[zeroIndex] = 1

    # first term
    C1 = sin(phi) / phi
    C1[zeroIndex] = 1  # is this right?  might be OK since C1 multiplies W

    # second term
    C2 = (1 - cos(phi)) / phi**2
    C2[zeroIndex] = 0.5  # won't matter because W^2 is small

    numObjs = expMap.shape[1]
    if numObjs == 1:  # case of single point
        W = np.reshape(W, [1, 3, 3])
        pass

    C1 = np.tile(
        np.reshape(C1, [numObjs, 1]),
        [1, 9]).reshape([numObjs, 3, 3])
    C2 = np.tile(
        np.reshape(C2, [numObjs, 1]),
        [1, 9]).reshape([numObjs, 3, 3])

    W2 = np.zeros([numObjs, 3, 3])

    for i in range(3):
        for j in range(3):
            W2[:, i, j] = np.sum(W[:, i, :]*W[:, :, j], 1)
            pass
        pass

    rmat = C1*W + C2 * W2
    rmat[:, 0, 0] += 1.
    rmat[:, 1, 1] += 1.
    rmat[:, 2, 2] += 1.

    return rmat.squeeze()
Пример #6
0
def rotMatOfExpMap_orig(expMap):
    """Original rotMatOfExpMap, used for comparison to optimized version
    """
    if isinstance(expMap, ndarray):
        if expMap.ndim != 2:
            if expMap.ndim == 1 and len(expMap) == 3:
                numObjs = 1
                expMap = expMap.reshape(3, 1)
            else:
                raise RuntimeError, "input is the wrong dimensionality"
        elif expMap.shape[0] != 3:
            raise RuntimeError(
                "input is the wrong shape along the 0-axis.  Yours is %d when is should be 3" % (expMap.shape[0])
            )
        else:
            numObjs = expMap.shape[1]
    elif isinstance(expMap, list) or isinstance(expMap, tuple):
        if len(expMap) != 3:
            raise RuntimeError, "for list/tuple input only one exponential map vector is allowed"
        else:
            if not isscalar(expMap[0]) or not isscalar(expMap[1]) or not isscalar(expMap[2]):
                raise RuntimeError, "for list/tuple input only one exponential map vector is allowed"
            else:
                numObjs = 1
                expMap = asarray(expMap).reshape(3, 1)

    phi = columnNorm(expMap)  # angles of rotation from exponential maps
    W = skewMatrixOfVector(expMap)  # skew matrices of exponential maps

    # Find tiny angles to avoid divide-by-zero and apply limits in expressions
    zeroIndex = phi < tinyRotAng
    phi[zeroIndex] = 1

    # first term
    C1 = sin(phi) / phi
    C1[zeroIndex] = 1

    # second term
    C2 = (1 - cos(phi)) / phi ** 2
    C2[zeroIndex] = 1

    if numObjs == 1:
        rmat = I3 + C1 * W + C2 * dot(W, W)
    else:
        rmat = zeros((numObjs, 3, 3))
        for i in range(numObjs):
            rmat[i, :, :] = I3 + C1[i] * W[i, :, :] + C2[i] * dot(W[i, :, :], W[i, :, :])

    return rmat
Пример #7
0
def rotMatOfExpMap_opt(expMap):
    """Optimized version of rotMatOfExpMap
    """
    if expMap.ndim == 1:
        expMap = expMap.reshape(3, 1)
    phi = atleast_1d(columnNorm(expMap)) # angles of rotation from exponential maps
    W   = skewMatrixOfVector(expMap)     # skew matrices of exponential maps

    # Find tiny angles to avoid divide-by-zero and apply limits in expressions
    zeroIndex = phi < tinyRotAng
    phi[zeroIndex] = 1


    # first term
    C1 = sin(phi) / phi
    C1[zeroIndex] = 1  # is this right?  might be OK since C1 multiplies W

    # second term
    C2 = (1 - cos(phi)) / phi**2
    C2[zeroIndex] = 0.5 # won't matter because W^2 is small

    numObjs = expMap.shape[1]
    if numObjs == 1: # case of single point
        W = numpy.reshape(W, [1, 3, 3])
        pass

    C1 = numpy.tile(numpy.reshape(C1, [numObjs, 1]), [1, 9]).reshape([numObjs,3,3])
    C2 = numpy.tile(numpy.reshape(C2, [numObjs, 1]), [1, 9]).reshape([numObjs,3,3])

    W2 = numpy.zeros([numObjs, 3, 3])

    for i in range(3):
        for j in range(3):
            W2[:, i, j] = numpy.sum(W[:, i, :]*W[:, :, j], 1)
            pass
        pass

    rmat = C1*W + C2 * W2
    rmat[:, 0, 0] += 1.
    rmat[:, 1, 1] += 1.
    rmat[:, 2, 2] += 1.

    return rmat.squeeze()
Пример #8
0
def assemble_grain_data(grain_data_list,
                        pos_offset=None,
                        rotation_offset=None):
    num_grain_files = len(grain_data_list)

    num_grains_list = [None] * num_grain_files

    for i in np.arange(num_grain_files):
        num_grains_list[i] = grain_data_list[i].shape[0]

    num_grains = np.sum(num_grains_list)

    grain_data = np.zeros([num_grains, grain_data_list[0].shape[1]])

    for i in np.arange(num_grain_files):

        tmp = copy.copy(grain_data_list[i])

        if pos_offset is not None:
            pos_tile = np.tile(pos_offset[:, i], [num_grains_list[i], 1])
            tmp[:, 6:9] = tmp[:, 6:9] + pos_tile
        #Needs Testing
        if rotation_offset is not None:
            rot_tile = np.tile(
                np.atleast_2d(rotation_offset[:, i]).T,
                [1, num_grains_list[i]])
            quat_tile = rot.quatOfExpMap(rot_tile)
            grain_quats = rot.quatOfExpMap(tmp[:, 3:6].T)
            new_quats = rot.quatProduct(grain_quats, quat_tile)

            sinang = mutil.columnNorm(new_quats[1:, :])
            ang = 2. * np.arcsin(sinang)
            axis = mutil.unitVector(new_quats[1:, :])
            tmp[:, 3:6] = np.tile(np.atleast_2d(ang).T, [1, 3]) * axis.T

        grain_data[int(np.sum(num_grains_list[:i])
                       ):int(np.sum(num_grains_list[:(i + 1)])), :] = tmp

    old_grain_numbers = copy.copy(grain_data[:, 0])
    grain_data[:, 0] = np.arange(num_grains)
    return grain_data, old_grain_numbers
Пример #9
0
def assemble_grain_data(grain_data_list,pos_offset=None,rotation_offset=None):
    num_grain_files=len(grain_data_list)    
    
    num_grains_list=[None]*num_grain_files
    
    for i in np.arange(num_grain_files):
        num_grains_list[i]=grain_data_list[i].shape[0]
        
    num_grains=np.sum(num_grains_list)  
    
    grain_data=np.zeros([num_grains,grain_data_list[0].shape[1]])    
    
    for i in np.arange(num_grain_files):
        
        tmp=copy.copy(grain_data_list[i])
        
        if pos_offset is not None:
            pos_tile=np.tile(pos_offset[:,i],[num_grains_list[i],1])
            tmp[:,6:9]=tmp[:,6:9]+pos_tile
        #Needs Testing    
        if rotation_offset is not None:  
            rot_tile=np.tile(np.atleast_2d(rotation_offset[:,i]).T,[1,num_grains_list[i]])
            quat_tile=rot.quatOfExpMap(rot_tile)
            grain_quats=rot.quatOfExpMap(tmp[:,3:6].T)
            new_quats=rot.quatProduct(grain_quats,quat_tile)
            
            sinang = mutil.columnNorm(new_quats[1:,:])
            ang=2.*np.arcsin(sinang)
            axis   = mutil.unitVector(new_quats[1:,:])
            tmp[:,3:6]=np.tile(np.atleast_2d(ang).T,[1,3])*axis.T

            
        grain_data[int(np.sum(num_grains_list[:i])):int(np.sum(num_grains_list[:(i+1)])),:]=tmp
        

    old_grain_numbers=copy.copy(grain_data[:,0])
    grain_data[:,0]=np.arange(num_grains)    
    return grain_data,old_grain_numbers
Пример #10
0
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
Пример #11
0
    def oe_pfig(self):
        """Make an omega-eta polefigure"""
        # some constants

        deg2rad = numpy.pi / 180.0
        radius = numpy.sqrt(2)
        offset = 2.5 * radius
        nocolor = 'none'
        pdir_cho = 'X'  # to come from choice interactor

        # parent window and data

        exp = wx.GetApp().ws
        p = self.GetParent()
        ome_eta = p.data
        hkldata = ome_eta.getData(self.idata)

        # axes/figure

        p.figure.delaxes(p.axes)
        p.axes = p.figure.gca()
        p.axes.set_autoscale_on(True)
        p.axes.set_aspect('equal')
        p.axes.axis([-2.0, offset + 2.0, -1.5, 1.5])

        # outlines for pole figure

        C1 = Circle((0, 0), radius)
        C2 = Circle((offset, 0), radius)
        outline_circles = [C1, C2]
        pc_outl = PatchCollection(outline_circles, facecolors=nocolor)
        p.axes.add_collection(pc_outl)

        # build the rectangles

        pf_rects = []

        tTh = exp.activeMaterial.planeData.getTTh()[self.idata]

        etas = ome_eta.etaEdges
        netas = len(etas) - 1
        deta = abs(etas[1] - etas[0])

        omes = ome_eta.omeEdges
        nomes = len(omes) - 1
        dome = abs(omes[1] - omes[0])

        if pdir_cho == 'X':
            pdir = numpy.c_[1, 0, 0].T  # X
        elif pdir_cho == 'Y':
            pdir = numpy.c_[0, 1, 0].T  # X
        elif pdir_cho == 'Z':
            pdir = numpy.c_[0, 0, 1].T  # X
            pass

        ii = 0
        for i in range(nomes):
            for j in range(netas):
                qc = makeMSV(tTh, etas[j] + 0.5 * deta, omes[i] + 0.5 * dome)

                qll = makeMSV(tTh, etas[j], omes[i])
                qlr = makeMSV(tTh, etas[j] + deta, omes[i])
                qur = makeMSV(tTh, etas[j] + deta, omes[i] + dome)
                qul = makeMSV(tTh, etas[j], omes[i] + dome)

                pdot_p = numpy.dot(qll.T, pdir) >= 0 \
                    and numpy.dot(qlr.T, pdir) >= 0 \
                    and numpy.dot(qur.T, pdir) >= 0 \
                    and numpy.dot(qul.T, pdir) >= 0

                pdot_m = numpy.dot(qll.T, pdir) < 0 \
                    and numpy.dot(qlr.T, pdir) < 0 \
                    and numpy.dot(qur.T, pdir) < 0 \
                    and numpy.dot(qul.T, pdir) < 0

                if pdot_p:
                    sgn = 1.0
                    ii += 1
                elif pdot_m:
                    sgn = -1.0
                    ii += 1
                elif not pdot_p and not pdot_m:
                    continue

                # the vertex chords
                qll = makeMSV(tTh, etas[j], omes[i]) - sgn * pdir
                qlr = makeMSV(tTh, etas[j] + deta, omes[i]) - sgn * pdir
                qur = makeMSV(tTh, etas[j] + deta, omes[i] + dome) - sgn * pdir
                qul = makeMSV(tTh, etas[j], omes[i] + dome) - sgn * pdir

                nll = columnNorm(qll)
                nlr = columnNorm(qlr)
                nur = columnNorm(qur)
                nul = columnNorm(qul)

                if pdir_cho == 'X':
                    pqll = nll * unitVector(qll[[1, 2]].reshape(2, 1))
                    pqlr = nlr * unitVector(qlr[[1, 2]].reshape(2, 1))
                    pqur = nur * unitVector(qur[[1, 2]].reshape(2, 1))
                    pqul = nul * unitVector(qul[[1, 2]].reshape(2, 1))
                elif pdir_cho == 'Y':
                    pqll = nll * unitVector(qll[[0, 2]].reshape(2, 1))
                    pqlr = nlr * unitVector(qlr[[0, 2]].reshape(2, 1))
                    pqur = nur * unitVector(qur[[0, 2]].reshape(2, 1))
                    pqul = nul * unitVector(qul[[0, 2]].reshape(2, 1))
                elif pdir_cho == 'Z':
                    pqll = nll * unitVector(qll[[0, 1]].reshape(2, 1))
                    pqlr = nlr * unitVector(qlr[[0, 1]].reshape(2, 1))
                    pqur = nur * unitVector(qur[[0, 1]].reshape(2, 1))
                    pqul = nul * unitVector(qul[[0, 1]].reshape(2, 1))

                xy = numpy.hstack([pqll, pqlr, pqur, pqul]).T
                if sgn == -1:
                    xy[:, 0] = xy[:, 0] + offset
                pf_rects.append(Polygon(xy, aa=False))
                pass
            pass

        cmap = matplotlib.cm.jet
        pf_coll = PatchCollection(pf_rects, cmap=cmap, edgecolors='None')
        pf_coll.set_array(numpy.array(hkldata.T.flatten()))
        p.axes.add_collection(pf_coll)

        p.canvas.draw()
        p.axes.axis('off')
        return
Пример #12
0
    def simulateLauePattern(self, planeData, minEnergy=5, maxEnergy=25, rMat_s=np.eye(3), rMat=None, vInv=None, doGnomonic=False):
        
        multipleEnergyRanges = False
        if hasattr(maxEnergy, '__len__'):
            assert len(maxEnergy) == len(minEnergy), 'energy cutoff ranges must have the same length'
            multipleEnergyRanges = True; lmin = []; lmax = []
            for i in range(len(maxEnergy)):
                lmin.append(processWavelength(maxEnergy[i]))
                lmax.append(processWavelength(minEnergy[i]))                
        else:
            lmin = processWavelength(maxEnergy)
            lmax = processWavelength(minEnergy)
        
        gvec_c = planeData.getPlaneNormals()
        hkls   = planeData.getSymHKLs() 
        dsp    = planeData.getPlaneSpacings()
        
        if rMat is None:
            rMat = [np.eye(3),]
        if vInv is None:
            vInv = [vInv_ref,]
        
        # rMult     = planeData.getMultiplicity()
        # nHKLs_tot = rMult.sum()
        # rMask     = np.ones(nHKLs_tot, dtype=bool)
        
        retval = []
        for iG in range(len(rMat)):
            tmp = {'detXY':[], 'gnoXY':[], 'angles':[], 'dspacing':[], 'hkl':[], 'energy':[]}
            for iHKL in range(planeData.nHKLs):                
                # stretch them: V^(-1) * R * Gc
                gvec_s_str = mutil.unitVector(
                    np.dot( vInv[iG], np.dot( rMat[iG], gvec_c[iHKL] ) ) )
                gvec_c_str = np.dot(rMat[iG].T, gvec_s_str)
                gvec_l_str = np.dot(rMat_s, gvec_s_str)
                #
                # dpts  = self.gVecToDet(gvec_c_str, rMat=rMat[iG], rMat_s=rMat_s)
                # gpts  = self.gVecToDet(gvec_c_str, rMat=rMat[iG], rMat_s=rMat_s, doGnomonic=True)
                dpts  = self.gVecToDet(gvec_c_str, rMat=rMat[iG], rMat_s=rMat_s)
                gpts  = self.gVecToDet(gvec_c_str, rMat=rMat[iG], rMat_s=rMat_s, doGnomonic=True)
                canIntersect = -np.isnan(dpts[0, :])
                npts_in = sum(canIntersect)
                if np.any(canIntersect):
                    dpts = dpts[:, canIntersect].reshape(3, npts_in)
                    dhkl = hkls[iHKL][:, canIntersect].reshape(3, npts_in)

                    gvl_hat = gvec_l_str[:, canIntersect].reshape(3, npts_in)
                    gvl_xy  = gvec_l_str[:2, canIntersect].reshape(2, npts_in)
                    
                    # dot with the beam
                    dotWbeam = np.dot(Z_ref.T, gvl_hat).flatten()

                    # angles
                    theta = piby2 - rot.arccosSafe( dotWbeam )
                    wlen  = 2*dsp[iHKL]*np.sin(theta)
                    eta   = np.arccos(gvl_xy[0, :])
                    
                    # find on spatial extent of detector
                    # for corner # xTest = np.logical_and(dpts[0, :] > 0, dpts[0, :] < self.cdim)
                    # for corner # yTest = np.logical_and(dpts[1, :] > 0, dpts[1, :] < self.rdim)
                    xTest = np.logical_and(dpts[0, :] > -0.5 * self.cdim, dpts[0, :] < 0.5 * self.cdim)
                    yTest = np.logical_and(dpts[1, :] > -0.5 * self.rdim, dpts[1, :] < 0.5 * self.rdim)
                    
                    onDetector  = np.logical_and(xTest, yTest)
                    if multipleEnergyRanges:
                        validEnergy = np.zeros(len(wlen), dtype=bool)
                        for i in range(len(lmin)):
                            validEnergy = validEnergy | np.logical_and(wlen >= lmin[i], wlen <= lmax[i])
                            pass
                    else:
                        validEnergy = np.logical_and(wlen >= lmin, wlen <= lmax)
                        pass
                    
                    keepers = np.logical_and(onDetector, validEnergy)

                    dsp_this = 1. / mutil.columnNorm(np.dot(planeData.latVecOps['B'], dhkl[:, keepers]))
                    
                    tmp['detXY'].append(dpts[:2, keepers])
                    tmp['gnoXY'].append(gpts[:2, keepers])
                    tmp['angles'].append(np.vstack([2*theta[keepers]*r2d, eta[keepers]*r2d]))
                    tmp['hkl'].append(dhkl[:, keepers])
                    tmp['dspacing'].append(dsp_this)
                    tmp['energy'].append(processWavelength(wlen[keepers]))
                else:
                    tmp['detXY'].append(np.empty((2, 0)))
                    tmp['gnoXY'].append(np.empty((2, 0)))
                    tmp['angles'].append(np.empty((2, 0)))
                    tmp['hkl'].append(np.empty((3, 0)))
                    tmp['dspacing'].append(np.empty(0))
                    tmp['energy'].append(np.empty(0))
                    pass
                pass
            retval.append(tmp)
        return retval
Пример #13
0
    def oe_pfig(self):
        """Make an omega-eta polefigure"""
        # some constants

        deg2rad = numpy.pi /180.0
        radius = numpy.sqrt(2)
        offset = 2.5*radius
        nocolor = 'none'
        pdir_cho = 'X'  # to come from choice interactor

        # parent window and data

        exp = wx.GetApp().ws
        p = self.GetParent()
        ome_eta = p.data
        hkldata = ome_eta.getData(self.idata)

        # axes/figure

        p.figure.delaxes(p.axes)
        p.axes = p.figure.gca()
        p.axes.set_autoscale_on(True)
        p.axes.set_aspect('equal')
        p.axes.axis([-2.0, offset+2.0, -1.5, 1.5])

        # outlines for pole figure

        C1 = Circle((0,0), radius)
        C2 = Circle((offset,0), radius)
        outline_circles = [C1, C2]
        pc_outl = PatchCollection(outline_circles, facecolors=nocolor)
        p.axes.add_collection(pc_outl)

        # build the rectangles

        pf_rects = []

        tTh = exp.activeMaterial.planeData.getTTh()[self.idata]

        etas  = ome_eta.etaEdges
        netas = len(etas) - 1
        deta = abs(etas[1] - etas[0])

        omes  = ome_eta.omeEdges
        nomes = len(omes) - 1
        dome = abs(omes[1] - omes[0])

        if pdir_cho == 'X':
            pdir = numpy.c_[1, 0, 0].T  # X
        elif pdir_cho == 'Y':
            pdir = numpy.c_[0, 1, 0].T  # X
        elif pdir_cho == 'Z':
            pdir = numpy.c_[0, 0, 1].T  # X
            pass

        ii = 0
        for i in range(nomes):
            for j in range(netas):
                qc = makeMSV(tTh, etas[j] + 0.5*deta, omes[i] + 0.5*dome)

                qll = makeMSV(tTh,        etas[j],        omes[i])
                qlr = makeMSV(tTh, etas[j] + deta,        omes[i])
                qur = makeMSV(tTh, etas[j] + deta, omes[i] + dome)
                qul = makeMSV(tTh,        etas[j], omes[i] + dome)

                pdot_p = numpy.dot(qll.T, pdir) >= 0 \
                    and numpy.dot(qlr.T, pdir) >= 0 \
                    and numpy.dot(qur.T, pdir) >= 0 \
                    and numpy.dot(qul.T, pdir) >= 0

                pdot_m = numpy.dot(qll.T, pdir) < 0 \
                    and numpy.dot(qlr.T, pdir) < 0 \
                    and numpy.dot(qur.T, pdir) < 0 \
                    and numpy.dot(qul.T, pdir) < 0

                if pdot_p:
                    sgn = 1.0
                    ii += 1
                elif pdot_m:
                    sgn = -1.0
                    ii += 1
                elif not pdot_p and not pdot_m:
                    continue

                # the vertex chords
                qll = makeMSV(tTh,        etas[j],        omes[i]) - sgn * pdir
                qlr = makeMSV(tTh, etas[j] + deta,        omes[i]) - sgn * pdir
                qur = makeMSV(tTh, etas[j] + deta, omes[i] + dome) - sgn * pdir
                qul = makeMSV(tTh,        etas[j], omes[i] + dome) - sgn * pdir

                nll = columnNorm(qll)
                nlr = columnNorm(qlr)
                nur = columnNorm(qur)
                nul = columnNorm(qul)

                if pdir_cho == 'X':
                    pqll = nll*unitVector(qll[[1, 2]].reshape(2, 1))
                    pqlr = nlr*unitVector(qlr[[1, 2]].reshape(2, 1))
                    pqur = nur*unitVector(qur[[1, 2]].reshape(2, 1))
                    pqul = nul*unitVector(qul[[1, 2]].reshape(2, 1))
                elif pdir_cho == 'Y':
                    pqll = nll*unitVector(qll[[0, 2]].reshape(2, 1))
                    pqlr = nlr*unitVector(qlr[[0, 2]].reshape(2, 1))
                    pqur = nur*unitVector(qur[[0, 2]].reshape(2, 1))
                    pqul = nul*unitVector(qul[[0, 2]].reshape(2, 1))
                elif pdir_cho == 'Z':
                    pqll = nll*unitVector(qll[[0, 1]].reshape(2, 1))
                    pqlr = nlr*unitVector(qlr[[0, 1]].reshape(2, 1))
                    pqur = nur*unitVector(qur[[0, 1]].reshape(2, 1))
                    pqul = nul*unitVector(qul[[0, 1]].reshape(2, 1))

                xy = numpy.hstack([pqll, pqlr, pqur, pqul]).T
                if sgn == -1:
                    xy[:, 0] = xy[:, 0] + offset
                pf_rects.append(Polygon(xy, aa=False))
                pass
            pass

        cmap=matplotlib.cm.jet
        pf_coll = PatchCollection(pf_rects, cmap=cmap, edgecolors='None')
        pf_coll.set_array(numpy.array(hkldata.T.flatten()))
        p.axes.add_collection(pf_coll)

        p.canvas.draw()
        p.axes.axis('off')
        return
Пример #14
0
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
Пример #15
0
def simulateLauePattern(hkls,
                        bMat,
                        rmat_d,
                        tvec_d,
                        panel_dims,
                        panel_buffer=5,
                        minEnergy=8,
                        maxEnergy=24,
                        rmat_s=np.eye(3),
                        grain_params=None,
                        distortion=None,
                        beamVec=None):

    if beamVec is None:
        beamVec = xfcapi.bVec_ref

    # parse energy ranges
    multipleEnergyRanges = False
    if hasattr(maxEnergy, '__len__'):
        assert len(maxEnergy) == len(minEnergy), \
            'energy cutoff ranges must have the same length'
        multipleEnergyRanges = True
        lmin = []
        lmax = []
        for i in range(len(maxEnergy)):
            lmin.append(processWavelength(maxEnergy[i]))
            lmax.append(processWavelength(minEnergy[i]))
    else:
        lmin = processWavelength(maxEnergy)
        lmax = processWavelength(minEnergy)

    # process crystal rmats and inverse stretches
    if grain_params is None:
        grain_params = np.atleast_2d(
            [0., 0., 0., 0., 0., 0., 1., 1., 1., 0., 0., 0.])

    n_grains = len(grain_params)

    # dummy translation vector... make input
    tvec_s = np.zeros((3, 1))

    # number of hkls
    nhkls_tot = hkls.shape[1]

    # unit G-vectors in crystal frame
    ghat_c = mutil.unitVector(np.dot(bMat, hkls))

    # pre-allocate output arrays
    xy_det = np.nan * np.ones((n_grains, nhkls_tot, 2))
    hkls_in = np.nan * np.ones((n_grains, 3, nhkls_tot))
    angles = np.nan * np.ones((n_grains, nhkls_tot, 2))
    dspacing = np.nan * np.ones((n_grains, nhkls_tot))
    energy = np.nan * np.ones((n_grains, nhkls_tot))
    """
    LOOP OVER GRAINS
    """

    for iG, gp in enumerate(grain_params):
        rmat_c = xfcapi.makeRotMatOfExpMap(gp[:3])
        tvec_c = gp[3:6].reshape(3, 1)
        vInv_s = mutil.vecMVToSymm(gp[6:].reshape(6, 1))

        # stretch them: V^(-1) * R * Gc
        ghat_s_str = mutil.unitVector(np.dot(vInv_s, np.dot(rmat_c, ghat_c)))
        ghat_c_str = np.dot(rmat_c.T, ghat_s_str)

        # project
        dpts = xfcapi.gvecToDetectorXY(ghat_c_str.T,
                                       rmat_d,
                                       rmat_s,
                                       rmat_c,
                                       tvec_d,
                                       tvec_s,
                                       tvec_c,
                                       beamVec=beamVec).T

        # check intersections with detector plane
        canIntersect = ~np.isnan(dpts[0, :])
        npts_in = sum(canIntersect)

        if np.any(canIntersect):
            dpts = dpts[:, canIntersect].reshape(2, npts_in)
            dhkl = hkls[:, canIntersect].reshape(3, npts_in)

            # back to angles
            tth_eta, gvec_l = xfcapi.detectorXYToGvec(dpts.T,
                                                      rmat_d,
                                                      rmat_s,
                                                      tvec_d,
                                                      tvec_s,
                                                      tvec_c,
                                                      beamVec=beamVec)
            tth_eta = np.vstack(tth_eta).T

            # warp measured points
            if distortion is not None:
                if len(distortion) == 2:
                    dpts = distortion[0](dpts, distortion[1], invert=True)

            # plane spacings and energies
            dsp = 1. / mutil.columnNorm(np.dot(bMat, dhkl))
            wlen = 2 * dsp * np.sin(0.5 * tth_eta[:, 0])

            # find on spatial extent of detector
            xTest = np.logical_and(
                dpts[0, :] >= -0.5 * panel_dims[1] + panel_buffer,
                dpts[0, :] <= 0.5 * panel_dims[1] - panel_buffer)
            yTest = np.logical_and(
                dpts[1, :] >= -0.5 * panel_dims[0] + panel_buffer,
                dpts[1, :] <= 0.5 * panel_dims[0] - panel_buffer)

            onDetector = np.logical_and(xTest, yTest)
            if multipleEnergyRanges:
                validEnergy = np.zeros(len(wlen), dtype=bool)
                for i in range(len(lmin)):
                    validEnergy = validEnergy | \
                        np.logical_and(wlen >= lmin[i], wlen <= lmax[i])
                    pass
            else:
                validEnergy = np.logical_and(wlen >= lmin, wlen <= lmax)
                pass

            # index for valid reflections
            keepers = np.where(np.logical_and(onDetector, validEnergy))[0]

            # assign output arrays
            xy_det[iG][keepers, :] = dpts[:, keepers].T
            hkls_in[iG][:, keepers] = dhkl[:, keepers]
            angles[iG][keepers, :] = tth_eta[keepers, :]
            dspacing[iG, keepers] = dsp[keepers]
            energy[iG, keepers] = processWavelength(wlen[keepers])
            pass
        pass
    return xy_det, hkls_in, angles, dspacing, energy
Пример #16
0
    def simulateLauePattern(self,
                            planeData,
                            minEnergy=5,
                            maxEnergy=25,
                            rMat_s=np.eye(3),
                            rMat=None,
                            vInv=None,
                            doGnomonic=False):

        multipleEnergyRanges = False
        if hasattr(maxEnergy, '__len__'):
            assert len(maxEnergy) == len(
                minEnergy), 'energy cutoff ranges must have the same length'
            multipleEnergyRanges = True
            lmin = []
            lmax = []
            for i in range(len(maxEnergy)):
                lmin.append(processWavelength(maxEnergy[i]))
                lmax.append(processWavelength(minEnergy[i]))
        else:
            lmin = processWavelength(maxEnergy)
            lmax = processWavelength(minEnergy)

        gvec_c = planeData.getPlaneNormals()
        hkls = planeData.getSymHKLs()
        dsp = planeData.getPlaneSpacings()

        if rMat is None:
            rMat = [
                np.eye(3),
            ]
        if vInv is None:
            vInv = [
                vInv_ref,
            ]

        # rMult     = planeData.getMultiplicity()
        # nHKLs_tot = rMult.sum()
        # rMask     = np.ones(nHKLs_tot, dtype=bool)

        retval = []
        for iG in range(len(rMat)):
            tmp = {
                'detXY': [],
                'gnoXY': [],
                'angles': [],
                'dspacing': [],
                'hkl': [],
                'energy': []
            }
            for iHKL in range(planeData.nHKLs):
                # stretch them: V^(-1) * R * Gc
                gvec_s_str = mutil.unitVector(
                    np.dot(vInv[iG], np.dot(rMat[iG], gvec_c[iHKL])))
                gvec_c_str = np.dot(rMat[iG].T, gvec_s_str)
                gvec_l_str = np.dot(rMat_s, gvec_s_str)
                #
                # dpts  = self.gVecToDet(gvec_c_str, rMat=rMat[iG], rMat_s=rMat_s)
                # gpts  = self.gVecToDet(gvec_c_str, rMat=rMat[iG], rMat_s=rMat_s, doGnomonic=True)
                dpts = self.gVecToDet(gvec_c_str, rMat=rMat[iG], rMat_s=rMat_s)
                gpts = self.gVecToDet(gvec_c_str,
                                      rMat=rMat[iG],
                                      rMat_s=rMat_s,
                                      doGnomonic=True)
                canIntersect = -np.isnan(dpts[0, :])
                npts_in = sum(canIntersect)
                if np.any(canIntersect):
                    dpts = dpts[:, canIntersect].reshape(3, npts_in)
                    dhkl = hkls[iHKL][:, canIntersect].reshape(3, npts_in)

                    gvl_hat = gvec_l_str[:, canIntersect].reshape(3, npts_in)
                    gvl_xy = gvec_l_str[:2, canIntersect].reshape(2, npts_in)

                    # dot with the beam
                    dotWbeam = np.dot(Z_ref.T, gvl_hat).flatten()

                    # angles
                    theta = piby2 - rot.arccosSafe(dotWbeam)
                    wlen = 2 * dsp[iHKL] * np.sin(theta)
                    eta = np.arccos(gvl_xy[0, :])

                    # find on spatial extent of detector
                    # for corner # xTest = np.logical_and(dpts[0, :] > 0, dpts[0, :] < self.cdim)
                    # for corner # yTest = np.logical_and(dpts[1, :] > 0, dpts[1, :] < self.rdim)
                    xTest = np.logical_and(dpts[0, :] > -0.5 * self.cdim,
                                           dpts[0, :] < 0.5 * self.cdim)
                    yTest = np.logical_and(dpts[1, :] > -0.5 * self.rdim,
                                           dpts[1, :] < 0.5 * self.rdim)

                    onDetector = np.logical_and(xTest, yTest)
                    if multipleEnergyRanges:
                        validEnergy = np.zeros(len(wlen), dtype=bool)
                        for i in range(len(lmin)):
                            validEnergy = validEnergy | np.logical_and(
                                wlen >= lmin[i], wlen <= lmax[i])
                            pass
                    else:
                        validEnergy = np.logical_and(wlen >= lmin,
                                                     wlen <= lmax)
                        pass

                    keepers = np.logical_and(onDetector, validEnergy)

                    dsp_this = 1. / mutil.columnNorm(
                        np.dot(planeData.latVecOps['B'], dhkl[:, keepers]))

                    tmp['detXY'].append(dpts[:2, keepers])
                    tmp['gnoXY'].append(gpts[:2, keepers])
                    tmp['angles'].append(
                        np.vstack(
                            [2 * theta[keepers] * r2d, eta[keepers] * r2d]))
                    tmp['hkl'].append(dhkl[:, keepers])
                    tmp['dspacing'].append(dsp_this)
                    tmp['energy'].append(processWavelength(wlen[keepers]))
                else:
                    tmp['detXY'].append(np.empty((2, 0)))
                    tmp['gnoXY'].append(np.empty((2, 0)))
                    tmp['angles'].append(np.empty((2, 0)))
                    tmp['hkl'].append(np.empty((3, 0)))
                    tmp['dspacing'].append(np.empty(0))
                    tmp['energy'].append(np.empty(0))
                    pass
                pass
            retval.append(tmp)
        return retval
Пример #17
0
    def makeScatteringVectors(hkls, rMat_c, bMat, wavelength, chiTilt=None):
        """
        modeled after QFromU.m
        """

        # basis vectors
        bHat_l = num.c_[ 0.,  0., -1.].T
        eHat_l = num.c_[ 1.,  0.,  0.].T

        zTol = 1.0e-7                       # zero tolerance for checking vectors

        gVec_s = []
        oangs0 = []
        oangs1 = []

        # these are the reciprocal lattice vectors in the CRYSTAL FRAME
        # ** NOTE **
        #   if strained, assumes that you handed it a bMat calculated from
        #   strained [a, b, c]
        gVec_c = num.dot( bMat, hkls )
        gHat_c = unitVector(gVec_c)

        dim0, nRefl = gVec_c.shape
        assert dim0 == 3, "Looks like something is wrong with your lattice plane normals son!"

        # extract 1/dspacing and sin of bragg angle
        dSpacingi = columnNorm(gVec_c).flatten()
        sintht    = 0.5 * wavelength * dSpacingi

        # move reciprocal lattice vectors to sample frame
        gHat_s = num.dot(rMat_c.squeeze(), gHat_c)

        if chiTilt is None:
            cchi = 1.
            schi = 0.
            rchi = num.eye(3)
        else:
            cchi = num.cos(chiTilt)
            schi = num.sin(chiTilt)
            rchi = num.array([[   1.,    0.,    0.],
                              [   0.,  cchi, -schi],
                              [   0.,  schi,  cchi]])
            pass

        a =  cchi * gHat_s[0, :]
        b = -cchi * gHat_s[2, :]
        c =  schi * gHat_s[1, :] - sintht

        # form solution
        abMag    = num.sqrt(a*a + b*b); assert num.all(abMag > 0), "Beam vector specification is infealible!"
        phaseAng = num.arctan2(b, a)
        rhs      = c / abMag; rhs[abs(rhs) > 1.] = num.nan
        rhsAng   = num.arcsin(rhs)

        # write ome angle output arrays (NaNs persist here)
        ome0 =          rhsAng - phaseAng
        ome1 = num.pi - rhsAng - phaseAng

        goodOnes_s = -num.isnan(ome0)

        eta0 = num.nan * num.ones_like(ome0)
        eta1 = num.nan * num.ones_like(ome1)

        # mark feasible reflections
        goodOnes   = num.tile(goodOnes_s, (1, 2)).flatten()

        numGood_s  = sum(goodOnes_s)
        numGood    = 2 * numGood_s
        tmp_eta    = num.empty(numGood)
        tmp_gvec   = num.tile(gHat_c, (1, 2))[:, goodOnes]
        allome     = num.hstack([ome0, ome1])

        for i in range(numGood):
            come = num.cos(allome[goodOnes][i])
            some = num.sin(allome[goodOnes][i])
            rome = num.array([[ come,    0.,  some],
                              [   0.,    1.,    0.],
                              [-some,    0.,  come]])
            rMat_s = num.dot(rchi, rome)
    	    gVec_l = num.dot(rMat_s,
                       num.dot(rMat_c, tmp_gvec[:, i].reshape(3, 1)
                       ) )
            tmp_eta[i] = num.arctan2(gVec_l[1], gVec_l[0])
            pass
        eta0[goodOnes_s] = tmp_eta[:numGood_s]
        eta1[goodOnes_s] = tmp_eta[numGood_s:]

        # make assoc tTh array
        tTh  = 2.*num.arcsin(sintht).flatten()
        tTh0 = tTh; tTh0[-goodOnes_s] = num.nan

        gVec_s = num.tile(dSpacingi, (3, 1)) * gHat_s
        oangs0 = num.vstack([tTh0.flatten(), eta0.flatten(), ome0.flatten()])
        oangs1 = num.vstack([tTh0.flatten(), eta1.flatten(), ome1.flatten()])

        return gVec_s, oangs0, oangs1