Exemplo n.º 1
0
def quatAverage(q_in, qsym):
    """
    """
    assert q_in.ndim == 2, 'input must be 2-s hstacked quats'

    # renormalize
    q_in = unitVector(q_in)

    # check to see num of quats is > 1
    if q_in.shape[1] < 3:
        if q_in.shape[1] == 1:
            q_bar = q_in
        else:
            ma, mq = misorientation(q_in[:, 0].reshape(4, 1),
                                    q_in[:, 1].reshape(4, 1), (qsym, ))
            q_bar = quatProduct(
                q_in[:, 0].reshape(4, 1),
                quatOfExpMap(0.5 * ma * unitVector(mq[1:].reshape(3, 1))))
    else:
        # use first quat as initial guess
        phi = 2. * arccos(q_in[0, 0])
        if phi <= finfo(float).eps:
            x0 = zeros(3)
        else:
            n = unitVector(q_in[1:, 0].reshape(3, 1))
            x0 = phi * n.flatten()
        results = leastsq(quatAverage_obj, x0, args=(q_in, qsym))
        phi = sqrt(sum(results[0] * results[0]))
        if phi <= finfo(float).eps:
            q_bar = c_[1., 0., 0., 0.].T
        else:
            n = results[0] / phi
            q_bar = hstack([cos(0.5 * phi), sin(0.5 * phi) * n]).reshape(4, 1)
    return q_bar
Exemplo n.º 2
0
def quatAverage(q_in, qsym):
    """
    """
    assert q_in.ndim == 2, 'input must be 2-s hstacked quats'

    # renormalize
    q_in = unitVector(q_in)

    # check to see num of quats is > 1
    if q_in.shape[1] < 3:
        if q_in.shape[1] == 1:
            q_bar = q_in
        else:
            ma, mq = misorientation(q_in[:, 0].reshape(4, 1),
                                    q_in[:, 1].reshape(4, 1), (qsym,))
            q_bar = quatProduct(q_in[:, 0].reshape(4, 1),
                                quatOfExpMap(0.5*ma*unitVector(mq[1:].reshape(3, 1))))
    else:
        # use first quat as initial guess
        phi = 2. * arccos(q_in[0, 0])
        if phi <= finfo(float).eps:
            x0 = zeros(3)
        else:
            n = unitVector(q_in[1:, 0].reshape(3, 1))
            x0 = phi*n.flatten()
        results = leastsq(quatAverage_obj, x0, args=(q_in, qsym))
        phi = sqrt(sum(results[0]*results[0]))
        if phi <= finfo(float).eps:
            q_bar = c_[1., 0., 0., 0.].T
        else:
            n     = results[0] / phi
            q_bar = hstack([cos(0.5*phi), sin(0.5*phi)*n]).reshape(4, 1)
    return q_bar
Exemplo n.º 3
0
def quatAverageCluster(q_in, qsym):
    """
    """
    assert q_in.ndim == 2, 'input must be 2-s hstacked quats'

    # renormalize
    q_in = unitVector(q_in)

    # check to see num of quats is > 1
    if q_in.shape[1] < 3:
        if q_in.shape[1] == 1:
            q_bar = q_in
        else:
            ma, mq = misorientation(q_in[:, 0].reshape(4, 1),
                                    q_in[:, 1].reshape(4, 1), (qsym, ))
            q_bar = quatProduct(
                q_in[:, 0].reshape(4, 1),
                quatOfExpMap(0.5 * ma * unitVector(mq[1:].reshape(3, 1))))
    else:
        # first drag to origin using first quat (arb!)
        q0 = q_in[:, 0].reshape(4, 1)
        qrot = dot(quatProductMatrix(invertQuat(q0), mult='left'), q_in)

        # second, re-cast to FR
        qrot = symmetry.toFundamentalRegion(qrot.squeeze(), crysSym=qsym)

        # compute arithmetic average
        q_bar = unitVector(average(qrot, axis=1).reshape(4, 1))

        # unrotate!
        q_bar = dot(quatProductMatrix(q0, mult='left'), q_bar)

        # re-map
        q_bar = symmetry.toFundamentalRegion(q_bar, crysSym=qsym)
    return q_bar
Exemplo n.º 4
0
def gen_schmid_tensors(pd,uvw,hkl):        

    # slip plane directions    
    slipdir  = mutil.unitVector( np.dot( pd.latVecOps['F'], uvw) ) #  2 -1 -1  0
    slipdir_sym  = sym.applySym(slipdir, pd.getQSym(), csFlag=False, cullPM=True, tol=1e-08)
    
    # slip plane plane normals
    n_plane = mutil.unitVector( np.dot( pd.latVecOps['B'], hkl ) )
    n_plane_sym = sym.applySym(n_plane, pd.getQSym(), csFlag=False, cullPM=True, tol=1e-08)

    
    num_slip_plane= n_plane_sym.shape[1]
    
    num_slip_sys=0
    for i in range(num_slip_plane):
        planeID = np.where(abs(np.dot(n_plane_sym[:, i],slipdir_sym)) < 1.e-8)[0]
        num_slip_sys +=planeID.shape[0]
        
    T= np.zeros((num_slip_sys, 3, 3))
    counter=0
        #
    for i in range(num_slip_plane):
        planeID = np.where(abs(np.dot(n_plane_sym[:, i],slipdir_sym)) < 1.e-8)[0]
        for j in np.arange(planeID.shape[0]):    
            T[counter, :, :] = np.dot(slipdir_sym[:, planeID[j]].reshape(3, 1), n_plane_sym[:, i].reshape(1, 3))
            counter+=1
    #Clean some round off errors        
    round_off_err=np.where(abs(T)<1e-8)
    T[round_off_err[0],round_off_err[1],round_off_err[2]]=0.

    return T
Exemplo n.º 5
0
def distanceToFiber(c, s, q, qsym, **kwargs):
    """
    """
    csymFlag = False
    B = I3

    arglen = len(kwargs)

    if len(c) != 3 or len(s) != 3:
        raise RuntimeError('c and/or s are not 3-vectors')

    # argument handling
    if arglen > 0:
        argkeys = list(kwargs.keys())
        for i in range(arglen):
            if argkeys[i] == 'centrosymmetry':
                csymFlag = kwargs[argkeys[i]]
            elif argkeys[i] == 'bmatrix':
                B = kwargs[argkeys[i]]
            else:
                raise RuntimeError("keyword arg \'%s\' is not recognized"
                                   % (argkeys[i]))

    c = unitVector(dot(B, asarray(c)))
    s = unitVector(asarray(s).reshape(3, 1))

    nq = q.shape[1]  # number of quaternions
    rmats = rotMatOfQuat(q)  # (nq, 3, 3)

    csym = applySym(c, qsym, csymFlag)  # (3, m)
    m = csym.shape[1]  # multiplicity

    if nq == 1:
        rc = dot(rmats, csym)  # apply q's to c's

        sdotrc = dot(s.T, rc).max()
    else:
        rc = multMatArray(
            rmats, tile(csym, (nq, 1, 1))
        )  # apply q's to c's

        sdotrc = dot(
            s.T,
            rc.swapaxes(1, 2).reshape(nq*m, 3).T
        ).reshape(nq, m).max(1)

    d = arccosSafe(array(sdotrc))

    return d
Exemplo n.º 6
0
def quatOfAngleAxis(angle, rotaxis):
    """
    make an hstacked array of quaternions from arrays of angle/axis pairs
    """
    if isinstance(angle, list):
        n = len(angle)
        angle = asarray(angle)
    elif isinstance(angle, float) or isinstance(angle, int):
        n = 1
    elif isinstance(angle, ndarray):
        n = angle.shape[0]
    else:
        raise RuntimeError, "angle argument is of incorrect type.  " \
            "must be a list, int, float, or ndarray."

    if rotaxis.shape[1] == 1:
        rotaxis = tile(rotaxis, (1, n))
    else:
        if rotaxis.shape[1] != n:
            raise RuntimeError, "rotation axes argument has incompatible shape"

    halfangle = 0.5*angle
    cphiby2 = cos(halfangle)
    sphiby2 = sin(halfangle)

    quat = vstack([cphiby2, tile(sphiby2, (3, 1)) * unitVector(rotaxis)])

    return fixQuat(quat)
Exemplo n.º 7
0
def quaternion_ball(qref, radius, num=500):
    """
    Makes a ball of randomly sampled quaternions within the specified misorientation of the supplied reference.

    Parameters
    ----------
    qref : array_like, (4,)
        Unit quaternion defining the reference orientation.
    radius : scalar
        Maximum misorientation in degrees.
    num : int, optional
        The number of orientations to generate. The default is 500.

    Returns
    -------
    The (4, num) array of quaternions around qref.

    """
    # make random angle/axis pairs
    rand_angs = np.radians(radius) * np.random.rand(num)
    rand_axes = mutil.unitVector(np.random.randn(3, num))

    # form quats
    qball = rot.quatOfAngleAxis(rand_angs, rand_axes)

    # recenter around reference orientation
    qref_mat = rot.quatProductMatrix(np.atleast_1d(qref).reshape(4, 1),
                                     mult='right').squeeze()

    return np.dot(qref_mat, qball)
Exemplo n.º 8
0
def quatOfAngleAxis(angle, rotaxis):
    """
    make an hstacked array of quaternions from arrays of angle/axis pairs
    """
    if isinstance(angle, list):
        n = len(angle)
        angle = asarray(angle)
    elif isinstance(angle, float) or isinstance(angle, int):
        n = 1
    elif isinstance(angle, ndarray):
        n = angle.shape[0]
    else:
        raise RuntimeError, "angle argument is of incorrect type.  " \
            "must be a list, int, float, or ndarray."

    if rotaxis.shape[1] == 1:
        rotaxis = tile(rotaxis, (1, n))
    else:
        if rotaxis.shape[1] != n:
            raise RuntimeError, "rotation axes argument has incompatible shape"

    halfangle = 0.5 * angle
    cphiby2 = cos(halfangle)
    sphiby2 = sin(halfangle)

    quat = vstack([cphiby2, tile(sphiby2, (3, 1)) * unitVector(rotaxis)])

    return fixQuat(quat)
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)
Exemplo n.º 10
0
def objFuncSX(pFit, pFull, pFlag, dFunc, dFlag,
              xyo_det, hkls_idx, bMat, vInv, wavelength,
              bVec, eVec, omePeriod,
              simOnly=False, returnScalarValue=returnScalarValue):
    """
    """
    npts   = len(xyo_det)

    refineFlag = np.hstack([pFlag, dFlag])

    # pFull[refineFlag] = pFit/scl[refineFlag]
    pFull[refineFlag] = pFit

    dParams = pFull[-len(dFlag):]
    xy_unwarped = dFunc(xyo_det[:, :2], dParams)

    # detector quantities
    rMat_d = xf.makeDetectorRotMat(pFull[:3])
    tVec_d = pFull[3:6].reshape(3, 1)

    # sample quantities
    chi    = pFull[6]
    tVec_s = pFull[7:10].reshape(3, 1)

    # crystal quantities
    rMat_c = xf.makeRotMatOfExpMap(pFull[10:13])
    tVec_c = pFull[13:16].reshape(3, 1)

    gVec_c = np.dot(bMat, hkls_idx)
    vMat_s = mutil.vecMVToSymm(vInv)                # stretch tensor comp matrix from MV notation in SAMPLE frame
    gVec_s = np.dot(vMat_s, np.dot(rMat_c, gVec_c)) # reciprocal lattice vectors in SAMPLE frame
    gHat_s = mutil.unitVector(gVec_s)               # unit reciprocal lattice vectors in SAMPLE frame
    gHat_c = np.dot(rMat_c.T, gHat_s)               # unit reciprocal lattice vectors in CRYSTAL frame

    match_omes, calc_omes = matchOmegas(xyo_det, hkls_idx, chi, rMat_c, bMat, wavelength,
                                        vInv=vInv, beamVec=bVec, etaVec=eVec, omePeriod=omePeriod)

    calc_xy = np.zeros((npts, 2))
    for i in range(npts):
        rMat_s = xfcapi.makeOscillRotMat([chi, calc_omes[i]])
        calc_xy[i, :] = xfcapi.gvecToDetectorXY(gHat_c[:, i],
                                                rMat_d, rMat_s, rMat_c,
                                                tVec_d, tVec_s, tVec_c,
                                                beamVec=bVec).flatten()
        pass
    if np.any(np.isnan(calc_xy)):
        print "infeasible pFull: may want to scale back finite difference step size"

    # return values
    if simOnly:
        retval = np.hstack([calc_xy, calc_omes.reshape(npts, 1)])
    else:
        diff_vecs_xy = calc_xy - xy_unwarped[:, :2]
        diff_ome     = xf.angularDifference( calc_omes, xyo_det[:, 2] )
        retval = np.hstack([diff_vecs_xy,
                            diff_ome.reshape(npts, 1)
                            ]).flatten()
        if returnScalarValue:
            retval = sum( retval )
    return retval
Exemplo n.º 11
0
def objFuncSX(pFit, pFull, pFlag, dFunc, dFlag,
              xyo_det, hkls_idx, bMat, vInv, wavelength,
              bVec, eVec, omePeriod,
              simOnly=False, returnScalarValue=returnScalarValue):
    """
    """
    npts   = len(xyo_det)

    refineFlag = np.hstack([pFlag, dFlag])

    # pFull[refineFlag] = pFit/scl[refineFlag]
    pFull[refineFlag] = pFit

    dParams = pFull[-len(dFlag):]
    xy_unwarped = dFunc(xyo_det[:, :2], dParams)

    # detector quantities
    rMat_d = xf.makeDetectorRotMat(pFull[:3])
    tVec_d = pFull[3:6].reshape(3, 1)

    # sample quantities
    chi    = pFull[6]
    tVec_s = pFull[7:10].reshape(3, 1)

    # crystal quantities
    rMat_c = xf.makeRotMatOfExpMap(pFull[10:13])
    tVec_c = pFull[13:16].reshape(3, 1)

    gVec_c = np.dot(bMat, hkls_idx)
    vMat_s = mutil.vecMVToSymm(vInv)                # stretch tensor comp matrix from MV notation in SAMPLE frame
    gVec_s = np.dot(vMat_s, np.dot(rMat_c, gVec_c)) # reciprocal lattice vectors in SAMPLE frame
    gHat_s = mutil.unitVector(gVec_s)               # unit reciprocal lattice vectors in SAMPLE frame
    gHat_c = np.dot(rMat_c.T, gHat_s)               # unit reciprocal lattice vectors in CRYSTAL frame

    match_omes, calc_omes = matchOmegas(xyo_det, hkls_idx, chi, rMat_c, bMat, wavelength,
                                        vInv=vInv, beamVec=bVec, etaVec=eVec, omePeriod=omePeriod)

    calc_xy = np.zeros((npts, 2))
    for i in range(npts):
        rMat_s = xfcapi.makeOscillRotMat([chi, calc_omes[i]])
        calc_xy[i, :] = xfcapi.gvecToDetectorXY(gHat_c[:, i],
                                                rMat_d, rMat_s, rMat_c,
                                                tVec_d, tVec_s, tVec_c,
                                                beamVec=bVec).flatten()
        pass
    if np.any(np.isnan(calc_xy)):
        print "infeasible pFull: may want to scale back finite difference step size"

    # return values
    if simOnly:
        retval = np.hstack([calc_xy, calc_omes.reshape(npts, 1)])
    else:
        diff_vecs_xy = calc_xy - xy_unwarped[:, :2]
        diff_ome     = xf.angularDifference( calc_omes, xyo_det[:, 2] )
        retval = np.hstack([diff_vecs_xy,
                            diff_ome.reshape(npts, 1)
                            ]).flatten()
        if returnScalarValue:
            retval = sum( retval )
    return retval
Exemplo n.º 12
0
def quatOfExpMap(expMap):
    """
    """
    angles = columnNorm(expMap)
    axes   = unitVector(expMap)

    quats = quatOfAngleAxis(angles, axes)
    return quats
Exemplo n.º 13
0
def quatOfExpMap(expMap):
    """
    """
    angles = columnNorm(expMap)
    axes = unitVector(expMap)

    quats = quatOfAngleAxis(angles, axes)
    return quats
Exemplo n.º 14
0
def angleAxisOfRotMat(R):
    """
    """
    if not isinstance(R, ndarray):
        raise RuntimeError, "Input must be a 2 or 3-d ndarray"
    else:
        rdim = R.ndim
        if rdim == 2:
            nrot = 1
            R = tile(R, (1, 1, 1))
        elif rdim == 3:
            nrot = R.shape[0]
        else:
            raise RuntimeError, "R array must be (3, 3) or (n, 3, 3); input has dimension %d" % (rdim)

    #
    #  Find angle of rotation.
    #
    ca = 0.5 * (R[:, 0, 0] + R[:, 1, 1] + R[:, 2, 2] - 1)

    angle = arccosSafe(ca)

    #
    #  Three cases for the angle:
    #
    #  *   near zero -- matrix is effectively the identity
    #  *   near pi   -- binary rotation; need to find axis
    #  *   neither   -- general case; can use skew part
    #
    tol = 1.0e-4

    anear0 = angle < tol

    angle[anear0] = 0

    raxis = vstack([R[:, 2, 1] - R[:, 1, 2], R[:, 0, 2] - R[:, 2, 0], R[:, 1, 0] - R[:, 0, 1]])
    raxis[:, anear0] = 1

    special = angle > pi - tol
    nspec = special.sum()
    if nspec > 0:
        tmp = R[special, :, :] + tile(I3, (nspec, 1, 1))
        tmpr = tmp.transpose(0, 2, 1).reshape(nspec * 3, 3).T

        tmpnrm = (tmpr * tmpr).sum(0).reshape(3, nspec)
        mx = tmpnrm.max(0)

        # remap indices
        maxInd = (tmpnrm == mx).nonzero()
        maxInd = c_[maxInd[0], maxInd[1]]

        tmprColInd = sort(maxInd[:, 0] + maxInd[:, 1] * nspec)

        saxis = tmpr[:, tmprColInd]

        raxis[:, special] = saxis

    return angle, unitVector(raxis)
Exemplo n.º 15
0
    def makePlaneData(hkls, lparms, qsym, symmGroup, strainMag, wavelength): # spots
        """
        hkls       : need to work with crystallography.latticePlanes
        lparms     : need to work with crystallography.latticePlanes
        laueGroup  : see symmetry module
        wavelength : wavelength
        strainMag  : swag of strian magnitudes
        """

        tempSetOutputDegrees(False)
        latPlaneData = latticePlanes(hkls, lparms,
                                     ltype=symmGroup,
                                     strainMag=strainMag,
                                     wavelength=wavelength)

        latVecOps = latticeVectors(lparms, symmGroup)

        hklDataList = []
        for iHKL in range(len(hkls.T)): # need transpose because of convention for hkls ordering

            # JVB # latVec = latPlaneData['normals'][:,iHKL]
            # JVB # # ... if not spots, may be able to work with a subset of these
            # JVB # latPlnNrmlList = symmetry.applySym(num.c_[latVec], qsym, csFlag=True, cullPM=False)

            # returns UN-NORMALIZED lattice plane normals
            latPlnNrmls = symmetry.applySym(
                num.dot(latVecOps['B'], hkls[:,iHKL].reshape(3, 1)),
                qsym,
                csFlag=True,
                cullPM=False)

            # check for +/- in symmetry group
            latPlnNrmlsM = symmetry.applySym(
                num.dot(latVecOps['B'], hkls[:,iHKL].reshape(3, 1)),
                qsym,
                csFlag=False,
                cullPM=False)

            csRefl = latPlnNrmls.shape[1] == latPlnNrmlsM.shape[1]

            # added this so that I retain the actual symmetric integer hkls as well
            symHKLs = num.array( num.round( num.dot(latVecOps['F'].T, latPlnNrmls) ), dtype='int' )

            hklDataList.append({
                'hklID'       : iHKL                           ,
                'hkl'         : hkls[:,iHKL]                   ,
                'tTheta'      : latPlaneData['tThetas'][iHKL]  ,
                'dSpacings'   : latPlaneData['dspacings'][iHKL],
                'tThetaLo'    : latPlaneData['tThetasLo'][iHKL],
                'tThetaHi'    : latPlaneData['tThetasHi'][iHKL],
                'latPlnNrmls' : unitVector(latPlnNrmls)        ,
                'symHKLs'     : symHKLs,
                'centrosym'   : csRefl
                })

        revertOutputDegrees()
        return latPlaneData, latVecOps, hklDataList
Exemplo n.º 16
0
def distanceToFiber(c, s, q, qsym, **kwargs):
    """
    """
    csymFlag = False
    B = I3

    arglen = len(kwargs)

    if len(c) != 3 or len(s) != 3:
        raise RuntimeError, 'c and/or s are not 3-vectors'

    # argument handling
    if arglen > 0:
        argkeys = kwargs.keys()
        for i in range(arglen):
            if argkeys[i] == 'centrosymmetry':
                csymFlag = kwargs[argkeys[i]]
            elif argkeys[i] == 'bmatrix':
                B = kwargs[argkeys[i]]
            else:
                raise RuntimeError('keyword arg \'%s\' is not recognized' \
                                   % (argkeys[i]))

    c = unitVector( dot(B, asarray(c)) )
    s = unitVector( asarray(s).reshape(3, 1) )

    nq    = q.shape[1]                  # number of quaternions
    rmats = rotMatOfQuat(q)             # (nq, 3, 3)

    csym = applySym(c, qsym, csymFlag)  # (3, m)
    m    = csym.shape[1]                # multiplicity

    if nq == 1:
        rc = dot(rmats, csym)           # apply q's to c's

        sdotrc = dot( s.T, rc ).max()
    else:
        rc = multMatArray( rmats, tile(csym, (nq, 1, 1)) ) # apply q's to c's

        sdotrc = dot( s.T, rc.swapaxes(1, 2).reshape(nq*m, 3).T ).reshape(nq, m).max(1)

    d = arccosSafe( array(sdotrc) )

    return d
Exemplo n.º 17
0
def quatAverageCluster(q_in, qsym):
    """
    """
    from symmetry import toFundamentalRegion

    assert q_in.ndim == 2, "input must be 2-s hstacked quats"

    # renormalize
    q_in = unitVector(q_in)

    # check to see num of quats is > 1
    if q_in.shape[1] < 3:
        if q_in.shape[1] == 1:
            q_bar = q_in
        else:
            ma, mq = misorientation(q_in[:, 0].reshape(4, 1), q_in[:, 1].reshape(4, 1), (qsym,))
            q_bar = quatProduct(q_in[:, 0].reshape(4, 1), quatOfExpMap(0.5 * ma * unitVector(mq[1:].reshape(3, 1))))
    else:
        # use first quat as initial guess
        phi = 2.0 * arccos(q_in[0, 0])
        if phi <= finfo(float).eps:
            x0 = zeros(3)
        else:
            n = unitVector(q_in[1:, 0].reshape(3, 1))
            x0 = phi * n.flatten()

        # first drag to origin using first quat (arb!)
        q0 = q_in[:, 0].reshape(4, 1)
        qrot = dot(quatProductMatrix(invertQuat(q0), mult="right"), q_in)

        # second, re-cast to FR
        qrot = toFundamentalRegion(qrot.squeeze(), crysSym=qsym)

        # compute arithmetic average
        q_bar = unitVector(average(qrot, axis=1).reshape(4, 1))

        # unrotate!
        q_bar = dot(quatProductMatrix(q0, mult="right"), q_bar)

        # re-map
        q_bar = toFundamentalRegion(q_bar, crysSym=qsym)
    return q_bar
Exemplo n.º 18
0
def gen_schmid_tensors(pd, uvw, hkl):

    # slip plane directions
    slipdir = mutil.unitVector(np.dot(pd.latVecOps['F'], uvw))  #  2 -1 -1  0
    slipdir_sym = sym.applySym(slipdir,
                               pd.getQSym(),
                               csFlag=False,
                               cullPM=True,
                               tol=1e-08)

    # slip plane plane normals
    n_plane = mutil.unitVector(np.dot(pd.latVecOps['B'], hkl))
    n_plane_sym = sym.applySym(n_plane,
                               pd.getQSym(),
                               csFlag=False,
                               cullPM=True,
                               tol=1e-08)

    num_slip_plane = n_plane_sym.shape[1]

    num_slip_sys = 0
    for i in range(num_slip_plane):
        planeID = np.where(
            abs(np.dot(n_plane_sym[:, i], slipdir_sym)) < 1.e-8)[0]
        num_slip_sys += planeID.shape[0]

    T = np.zeros((num_slip_sys, 3, 3))
    counter = 0
    #
    for i in range(num_slip_plane):
        planeID = np.where(
            abs(np.dot(n_plane_sym[:, i], slipdir_sym)) < 1.e-8)[0]
        for j in np.arange(planeID.shape[0]):
            T[counter, :, :] = np.dot(slipdir_sym[:, planeID[j]].reshape(3, 1),
                                      n_plane_sym[:, i].reshape(1, 3))
            counter += 1
    #Clean some round off errors
    round_off_err = np.where(abs(T) < 1e-8)
    T[round_off_err[0], round_off_err[1], round_off_err[2]] = 0.

    return T
Exemplo n.º 19
0
def quatAverageCluster(q_in, qsym):
    """
    """
    from symmetry import toFundamentalRegion

    assert q_in.ndim == 2, 'input must be 2-s hstacked quats'

    # renormalize
    q_in = unitVector(q_in)

    # check to see num of quats is > 1
    if q_in.shape[1] < 3:
        if q_in.shape[1] == 1:
            q_bar = q_in
        else:
            ma, mq = misorientation(q_in[:, 0].reshape(4, 1),
                                    q_in[:, 1].reshape(4, 1), (qsym,))
            q_bar = quatProduct(q_in[:, 0].reshape(4, 1),
                                quatOfExpMap(0.5*ma*unitVector(mq[1:].reshape(3, 1))))
    else:
        # first drag to origin using first quat (arb!)
        q0 = q_in[:, 0].reshape(4, 1)
        qrot = dot(
            quatProductMatrix( invertQuat( q0 ), mult='left' ),
            q_in)

        # second, re-cast to FR
        qrot = toFundamentalRegion(qrot.squeeze(), crysSym=qsym)

        # compute arithmetic average
        q_bar = unitVector(average(qrot, axis=1).reshape(4, 1))

        # unrotate!
        q_bar = dot(
            quatProductMatrix( q0, mult='left' ),
            q_bar)

        # re-map
        q_bar = toFundamentalRegion(q_bar, crysSym=qsym)
    return q_bar
Exemplo n.º 20
0
def drawLines(pw, pointLists=[],
              netStyle = None, netNDiv = 12, netAlpha = 0.5, rMat=None,
              southern=False, invertFromSouthern=True,
              origin=(0.,0.), r=1.0):

    x0, y0 = origin

    lines = pw.a.get_lines()
    for line in lines:
        line.remove()

    ringAngs = num.linspace(0,num.pi*2.,181)
    if netStyle:
        arcAngsM  = num.linspace(-num.pi/2.,num.pi/2.,91)
        arcAngsL  = num.linspace(0, num.pi, 181)
        rMat_yDiv = ors.RotInv(-num.pi/netNDiv, [0,1,0]).toMatrix()
    pw(r*num.cos(ringAngs)+x0,r*num.sin(ringAngs)+y0,style='k-')

    if netStyle:
        nVMerid = num.vstack( ( num.cos(arcAngsM), num.sin(arcAngsM), num.zeros(len(arcAngsM)) ) )
        for iDiv in range(netNDiv-1):
            nVMerid = num.dot(rMat_yDiv, nVMerid)
            eaProj = n2eap(nVMerid, flip=False)
            pw(r*eaProj[0,:]+x0, r*eaProj[1,:]+y0, alpha=netAlpha, style=netStyle)
        for latAng in num.pi/netNDiv*num.arange(1,netNDiv):
            polZ = num.cos(latAng)
            polR = num.sin(latAng)
            nVLat = num.vstack( ( polR*num.cos(arcAngsL), polZ*num.ones(len(arcAngsL)), polR*num.sin(arcAngsL)) )
            eaProj = n2eap(nVLat, flip=False)
            pw(r*eaProj[0,:]+x0, r*eaProj[1,:]+y0, alpha=netAlpha, style=netStyle)
    'done with drawing net'

    for points, pwKWArgs in pointLists:
        nVecs  = matrixutil.unitVector(points)
        if rMat is not None:
            'rotate as did elsewhere'
            nVecs = num.dot(rMat, nVecs)
        bNVecsS = nVecs[2,:] < 0
        if southern:
            nVecsS = nVecs[:,bNVecsS]
            nVecsS = fromSouthern(nVecsS, invertFromSouthern)
            eaProj = n2eap(nVecsS, flip=False)
            pw(r*eaProj[0,:]+x0, r*eaProj[1,:]+y0, **pwKWArgs)
        else:
            nVecsN = nVecs[:,num.logical_not(bNVecsS)]
            eaProj = n2eap(nVecsN, flip=False)
            pw(r*eaProj[0,:]+x0, r*eaProj[1,:]+x0, **pwKWArgs)
    'done with pointLists'

    return
Exemplo n.º 21
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)
Exemplo n.º 22
0
def millerBravaisDirectionToVector(dir_ind, a=1.0, c=1.0):
    """
    converts direction indices into a unit vector in the crystal frame

    INPUT [uv.w] the Miller-Bravais convention in the hexagonal basis {a1, a2, a3, c}.  
    The basis for the output, {o1, o2, o3}, is chosen such that

    o1 || a1
    o3 || c
    o2 = o3 ^ o1
    """
    dir_ind = num.atleast_2d(dir_ind)
    num_in = len(dir_ind)
    u = dir_ind[:, 0]
    v = dir_ind[:, 1]
    w = dir_ind[:, 2]
    return unitVector(num.vstack([1.5 * u * a, sqrt3by2 * (2.0 * v + u) * a, w * c]).reshape(3, num_in))
Exemplo n.º 23
0
def fixQuat(q):
    """
    flip to positive q0 and normalize
    """
    qdims = q.ndim
    if qdims == 3:
        l, m, n = q.shape
        assert m == 4, 'your 3-d quaternion array isn\'t the right shape'
        q = q.transpose(0, 2, 1).reshape(l*n, 4).T

    qfix = unitVector(q)

    q0negative = qfix[0, ] < 0
    qfix[:, q0negative] = -1*qfix[:, q0negative]

    if qdims == 3:
        qfix = qfix.T.reshape(l, n, 4).transpose(0, 2, 1)

    return qfix
Exemplo n.º 24
0
def fixQuat(q):
    """
    flip to positive q0 and normalize
    """
    qdims = q.ndim
    if qdims == 3:
        l, m, n = q.shape
        assert m == 4, 'your 3-d quaternion array isn\'t the right shape'
        q = q.transpose(0, 2, 1).reshape(l * n, 4).T

    qfix = unitVector(q)

    q0negative = qfix[0, ] < 0
    qfix[:, q0negative] = -1 * qfix[:, q0negative]

    if qdims == 3:
        qfix = qfix.T.reshape(l, n, 4).transpose(0, 2, 1)

    return qfix
Exemplo n.º 25
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
Exemplo n.º 26
0
def run_cluster(complPG, qfib, qsym,
                cl_radius=cl_radius, min_compl=min_compl):
    """
    """
    start = time.clock()                      # time this

    # # use transforms module for distance
    # quatDistance = lambda x, y: xf.quat_distance(x, y, qsym)

    # use compiled module for distance
    # just to be safe, must order qsym as C-contiguous
    qsym  = np.array(qsym.T, order='C').T
    quatDistance = lambda x, y: xfcapi.quat_distance(np.array(x, order='C'), \
                                                     np.array(y, order='C'), \
                                                     qsym)

    qfib_r = qfib[:, np.r_[complPG] > min_compl]

    print "Feeding %d orientations above %.1f%% to clustering" % (qfib_r.shape[1], 100*min_compl)

    if haveScikit:
        print "Using scikit..."
        pdist = pairwise_distances(qfib_r.T, metric=quatDistance, n_jobs=-1)
        core_samples, labels = dbscan(pdist, eps=d2r*cl_radius, min_samples=1, metric='precomputed')
        cl = np.array(labels, dtype=int) + 1
    else:
        print "Using fclusterdata with a tolerance of %f degrees..." % (cl_radius)
        cl = cluster.hierarchy.fclusterdata(qfib_r.T, d2r*cl_radius, criterion='distance', metric=quatDistance)

    nblobs = len(np.unique(cl))

    qbar = np.zeros((4, nblobs))
    for i in range(nblobs):
        npts = sum(cl == i + 1)
        qbar[:, i] = mutil.unitVector(
            np.sum(qfib[:, np.r_[complPG] > min_compl][:, cl == i + 1].reshape(4, npts), axis=1).reshape(4, 1)).flatten()
    elapsed = (time.clock() - start)

    print "clustering took %f seconds" % (elapsed)
    return qbar, cl
Exemplo n.º 27
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
Exemplo n.º 28
0
def find_orientations(cfg, hkls=None, clean=False, profile=False, nsim=100):
    print('ready to run find_orientations')
    # %%
    # =============================================================================
    # SEARCH SPACE GENERATION
    # =============================================================================

    hedm = cfg.instrument.hedm
    plane_data = cfg.material.plane_data

    ncpus = cfg.multiprocessing

    # for indexing
    active_hkls = cfg.find_orientations.orientation_maps.active_hkls
    fiber_ndiv = cfg.find_orientations.seed_search.fiber_ndiv
    fiber_seeds = cfg.find_orientations.seed_search.hkl_seeds
    on_map_threshold = cfg.find_orientations.threshold

    # for clustering
    cl_radius = cfg.find_orientations.clustering.radius
    min_compl = cfg.find_orientations.clustering.completeness
    compl_thresh = cfg.find_orientations.clustering.completeness

    eta_ome = get_eta_ome(cfg, clean=clean)

    print("INFO:\tgenerating search quaternion list using %d processes" %
          ncpus)
    start = timeit.default_timer()
    qfib = generate_orientation_fibers(eta_ome,
                                       hedm.chi,
                                       on_map_threshold,
                                       fiber_seeds,
                                       fiber_ndiv,
                                       ncpus=ncpus)
    print("INFO:\t\t...took %f seconds" % (timeit.default_timer() - start))
    print("INFO: will test %d quaternions using %d processes" %
          (qfib.shape[1], ncpus))

    # %%
    # =============================================================================
    # ORIENTATION SCORING
    # =============================================================================

    scoredq_filename = 'scored_orientations_' + analysis_id(cfg) + '.npz'

    print("INFO:\tusing map search with paintGrid on %d processes" % ncpus)
    start = timeit.default_timer()

    completeness = indexer.paintGrid(
        qfib,
        eta_ome,
        etaRange=np.radians(cfg.find_orientations.eta.range),
        omeTol=np.radians(cfg.find_orientations.omega.tolerance),
        etaTol=np.radians(cfg.find_orientations.eta.tolerance),
        omePeriod=np.radians(cfg.find_orientations.omega.period),
        threshold=on_map_threshold,
        doMultiProc=ncpus > 1,
        nCPUs=ncpus)
    print("INFO:\t\t...took %f seconds" % (timeit.default_timer() - start))
    completeness = np.array(completeness)

    # export scored orientations
    np.savez_compressed(scoredq_filename,
                        quaternions=qfib,
                        completeness=completeness)
    print("INFO:\tsaved scored orientations to file: '%s'" %
          (scoredq_filename))

    # %%
    # =============================================================================
    # CLUSTERING AND GRAINS OUTPUT
    # =============================================================================

    if not os.path.exists(cfg.analysis_dir):
        os.makedirs(cfg.analysis_dir)
    qbar_filename = 'accepted_orientations_' + analysis_id(cfg) + '.dat'

    print("INFO:\trunning clustering using '%s'" %
          cfg.find_orientations.clustering.algorithm)
    start = timeit.default_timer()

    # Simulate N random grains to get neighborhood size
    print("INFO:\trunning %d simulations to determine neighborhood size" %
          nsim)
    seed_hkl_ids = [
        plane_data.hklDataList[active_hkls[i]]['hklID'] for i in fiber_seeds
    ]

    # need ome_ranges from imageseries
    # CAVEAT: assumes that all imageseries have same omega ranges!!!
    oims = OmegaImageSeries(cfg.image_series.itervalues().next())
    ome_ranges = [(np.radians([i['ostart'], i['ostop']]))
                  for i in oims.omegawedges.wedges]

    if seed_hkl_ids is not None:
        rand_q = mutil.unitVector(np.random.randn(4, nsim))
        rand_e = np.tile(2.*np.arccos(rand_q[0, :]), (3, 1)) \
          * mutil.unitVector(rand_q[1:, :])
        refl_per_grain = np.zeros(nsim)
        num_seed_refls = np.zeros(nsim)
        grain_param_list = np.vstack([
            rand_e,
            np.zeros((3, nsim)),
            np.tile(cnst.identity_6x1, (nsim, 1)).T
        ]).T
        sim_results = hedm.simulate_rotation_series(
            plane_data,
            grain_param_list,
            eta_ranges=np.radians(cfg.find_orientations.eta.range),
            ome_ranges=ome_ranges,
            ome_period=np.radians(cfg.find_orientations.omega.period))

        refl_per_grain = np.zeros(nsim)
        seed_refl_per_grain = np.zeros(nsim)
        for sim_result in sim_results.itervalues():
            for i, refl_ids in enumerate(sim_result[0]):
                refl_per_grain[i] += len(refl_ids)
                seed_refl_per_grain[i] += np.sum(
                    [sum(refl_ids == hkl_id) for hkl_id in seed_hkl_ids])

        min_samples = max(
            int(
                np.floor(0.5 * cfg.find_orientations.clustering.completeness *
                         min(seed_refl_per_grain))), 2)
        mean_rpg = int(np.round(np.average(refl_per_grain)))
    else:
        min_samples = 1
        mean_rpg = 1

    print("INFO:\tmean reflections per grain: %d" % mean_rpg)
    print("INFO:\tneighborhood size: %d" % min_samples)

    qbar, cl = run_cluster(completeness,
                           qfib,
                           plane_data.getQSym(),
                           cfg,
                           min_samples=min_samples,
                           compl_thresh=compl_thresh,
                           radius=cl_radius)

    print("INFO:\t\t...took %f seconds" % (timeit.default_timer() - start))
    print("INFO:\tfound %d grains; saved to file: '%s'" %
          (qbar.shape[1], qbar_filename))

    np.savetxt(qbar_filename, qbar.T, fmt='%.18e', delimiter='\t')

    gw = instrument.GrainDataWriter(
        os.path.join(cfg.analysis_dir, 'grains.out'))
    grain_params_list = []
    for gid, q in enumerate(qbar.T):
        phi = 2 * np.arccos(q[0])
        n = xfcapi.unitRowVector(q[1:])
        grain_params = np.hstack([phi * n, cnst.zeros_3, cnst.identity_6x1])
        gw.dump_grain(gid, 1., 0., grain_params)
        grain_params_list.append(grain_params)
    gw.close()
Exemplo n.º 29
0
def check_indexing_plots(cfg_filename, plot_trials=False, plot_from_grains=False):
    cfg = config.open(cfg_filename)[0]    # use first block, like indexing

    working_dir = cfg.working_dir
    analysis_dir = os.path.join(working_dir, cfg.analysis_name)
    
    #instrument parameters
    icfg = get_instrument_parameters(cfg)
    chi = icfg['oscillation_stage']['chi']

    # load maps that were used
    oem = cPickle.load(
        open(cfg.find_orientations.orientation_maps.file, 'r')
        )
    nmaps = len(oem.dataStore)
    omeEdges = np.degrees(oem.omeEdges); nome = len(omeEdges) - 1
    etaEdges = np.degrees(oem.etaEdges); neta = len(etaEdges) - 1
    delta_ome = abs(omeEdges[1]-omeEdges[0])

    full_ome_range = xf.angularDifference(omeEdges[0], omeEdges[-1]) == 0
    full_eta_range = xf.angularDifference(etaEdges[0], etaEdges[-1]) == 0
    
    # grab plane data and figure out IDs of map HKLS
    pd = oem.planeData
    gvids = [pd.hklDataList[i]['hklID'] for i in np.where(pd.exclusions == False)[0].tolist()]

    # load orientations
    quats = np.atleast_2d(np.loadtxt(os.path.join(working_dir, 'accepted_orientations.dat')))
    if plot_trials:
        scored_trials = np.load(os.path.join(working_dir, 'scored_orientations.dat'))
        quats = scored_orientations[:4, scored_orientations[-1, :] >= cfg.find_orientations.clustering.completeness]
        pass
    expMaps = np.tile(2. * np.arccos(quats[:, 0]), (3, 1))*unitVector(quats[:, 1:].T)

    ##########################################
    #      SPECIAL CASE FOR FIT GRAINS       #
    ##########################################
    if plot_from_grains:
        distortion = (GE_41RT, icfg['detector']['distortion']['parameters'])
        #
        grain_table = np.atleast_2d(np.loadtxt(os.path.join(analysis_dir, 'grains.out')))
        ngrains = len(grain_table)
        #
        expMaps = grain_table[:, 3:6]
        tVec_c = grain_table[:, 6:9]
        vInv = grain_table[:, 6:12]
        #
        rMat_d = xf.makeDetectorRotMat(icfg['detector']['transform']['tilt_angles'])
        tVec_d = np.vstack(icfg['detector']['transform']['t_vec_d'])
        #
        chi = icfg['oscillation_stage']['chi']
        tVec_s = np.vstack(icfg['oscillation_stage']['t_vec_s'])
        #
        oes = np.zeros(oem.dataStore.shape)
        for i_grn in range(ngrains):
            spots_table = np.loadtxt(os.path.join(analysis_dir, 'spots_%05d.out' %i_grn))
            idx_m = spots_table[:, 0] >= 0
            for i_map in range(nmaps):
                idx_g = spots_table[:, 1] == gvids[i_map]
                idx = np.logical_and(idx_m, idx_g)
                nrefl = sum(idx)
                
                omes_fit = xf.mapAngle(spots_table[idx, 9], np.radians(cfg.find_orientations.omega.period), units='radians')
                xy_det = spots_table[idx, -3:]
                xy_det[:, 2] = np.zeros(nrefl)
                
                rMat_s_array = xfcapi.makeOscillRotMatArray(chi, omes_fit)
                
                # form in-plane vectors for detector points list in DETECTOR FRAME
                P2_d = xy_det.T
                
                # in LAB FRAME
                P2_l = np.dot(rMat_d, P2_d) + tVec_d # point on detector
                P0_l = np.hstack(
                    [tVec_s + np.dot(rMat_s_array[j], tVec_c[i_grn, :].reshape(3, 1)) for j in range(nrefl)]
                ) # origin of CRYSTAL FRAME

                # diffraction unit vector components in LAB FRAME
                dHat_l = unitVector(P2_l - P0_l)
                P2_l = np.dot(rMat_d, xy_det.T) + tVec_d
                
                # angles for reference frame
                dHat_ref_l = unitVector(P2_l)
    
                # append etas and omes
                etas_fit = np.arctan2(dHat_ref_l[1, :], dHat_ref_l[0, :]).flatten()
           
                # find indices, then truncate or wrap
                i_ome = cellIndices(oem.omeEdges, omes_fit)
                if full_ome_range:
                    i_ome[i_ome < 0] = np.mod(i_ome, nome) + 1
                    i_ome[i_ome >= nome] = np.mod(i_ome, nome)
                else:
                    incl = np.logical_or(i_ome >= 0, i_ome < nome)
                    i_ome = i_ome[incl]
                j_eta = cellIndices(oem.etaEdges, etas_fit)
                if full_eta_range:
                    j_eta[j_eta < 0] = np.mod(j_eta, neta) + 1
                    j_eta[j_eta >= neta] = np.mod(j_eta, neta)
                else:
                    incl = np.logical_or(j_eta >= 0, j_eta < neta)
                    j_eta = j_eta[incl]

                #if np.max(i_ome) >= nome or np.min(i_ome) < 0 or np.max(j_eta) >= neta or np.min(j_eta) < 0:
                #    import pdb; pdb.set_trace()
                # add to map
                oes[i_map][i_ome, j_eta] = 1
            pass
        pass
    
    # simulate quaternion points
    if not plot_from_grains:
        oes = simulateOmeEtaMaps(omeEdges, etaEdges, pd,
                                 expMaps,
                                 chi=chi,
                                 etaTol=0.01, omeTol=0.01,
                                 etaRanges=None, omeRanges=None,
                                 bVec=xf.bVec_ref, eVec=xf.eta_ref, vInv=xf.vInv_ref)
    
    # tick labling
    omes = np.degrees(oem.omeEdges)
    etas = np.degrees(oem.etaEdges)
    num_ticks = 7
    xmin = np.amin(etas); xmax = np.amax(etas)
    dx = (xmax - xmin) / (num_ticks - 1.); dx1 = (len(etas) - 1) / (num_ticks - 1.)
    xtlab = ["%.0f" % (xmin + i*dx) for i in range(num_ticks)]
    xtloc = np.array([i*dx1 for i in range(num_ticks)]) - 0.5
    ymin = np.amin(omes); ymax = np.amax(omes)
    dy = (ymax - ymin) / (num_ticks - 1.); dy1 = (len(omes) - 1) / (num_ticks - 1.)
    ytlab = ["%.0f" % (ymin + i*dy) for i in range(num_ticks)]
    ytloc = np.array([i*dy1 for i in range(num_ticks)]) - 0.5
    
    # Plot the three kernel density estimates
    n_maps = len(oem.iHKLList)
    
    fig_list =[plt.figure(num=i+1) for i in range(n_maps)]
    ax_list = [fig_list[i].gca() for i in range(n_maps)]
    for i_map in range(n_maps):
        y, x = np.where(oes[i_map] > 0)
        ax_list[i_map].hold(True)
        ax_list[i_map].imshow(oem.dataStore[i_map] > 0.1, cmap=cm.bone)
        ax_list[i_map].set_title(r'Map for $\{%d %d %d\}$' %tuple(pd.hkls[:, i_map]))
        ax_list[i_map].set_xlabel(r'Azimuth channel, $\eta$; $\Delta\eta=%.3f$' %delta_ome)
        ax_list[i_map].set_ylabel(r'Rotation channel, $\omega$; $\Delta\omega=%.3f$' %delta_ome)
        ax_list[i_map].plot(x, y, 'c+')
        ax_list[i_map].xaxis.set_ticks(xtloc)
        ax_list[i_map].xaxis.set_ticklabels(xtlab)
        ax_list[i_map].yaxis.set_ticks(ytloc)
        ax_list[i_map].yaxis.set_ticklabels(ytlab)
        ax_list[i_map].axis('tight')
    plt.show()
    return fig_list, oes
Exemplo n.º 30
0
    def simulate_laue_pattern(self, crystal_data,
                              minEnergy=5., maxEnergy=35.,
                              rmat_s=None, tvec_s=None,
                              grain_params=None,
                              beam_vec=None):
        """
        """
        if isinstance(crystal_data, PlaneData):

            plane_data = crystal_data

            # grab the expanded list of hkls from plane_data
            hkls = np.hstack(plane_data.getSymHKLs())

            # and the unit plane normals (G-vectors) in CRYSTAL FRAME
            gvec_c = np.dot(plane_data.latVecOps['B'], hkls)
        elif len(crystal_data) == 2:
            # !!! should clean this up
            hkls = np.array(crystal_data[0])
            bmat = crystal_data[1]
            gvec_c = np.dot(bmat, hkls)
        else:
            raise(RuntimeError, 'argument list not understood')
        nhkls_tot = hkls.shape[1]

        # parse energy ranges
        # TODO: allow for spectrum parsing
        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(ct.keVToAngstrom(maxEnergy[i]))
                lmax.append(ct.keVToAngstrom(minEnergy[i]))
        else:
            lmin = ct.keVToAngstrom(maxEnergy)
            lmax = ct.keVToAngstrom(minEnergy)

        # parse grain parameters kwarg
        if grain_params is None:
            grain_params = np.atleast_2d(
                np.hstack([np.zeros(6), ct.identity_6x1])
            )
        n_grains = len(grain_params)

        # sample rotation
        if rmat_s is None:
            rmat_s = ct.identity_3x3

        # dummy translation vector... make input
        if tvec_s is None:
            tvec_s = ct.zeros_3

        # beam vector
        if beam_vec is None:
            beam_vec = ct.beam_vec

        # =========================================================================
        # LOOP OVER GRAINS
        # =========================================================================

        # 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))
        for iG, gp in enumerate(grain_params):
            rmat_c = 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
            gvec_s_str = np.dot(vInv_s, np.dot(rmat_c, gvec_c))
            ghat_c_str = mutil.unitVector(np.dot(rmat_c.T, gvec_s_str))

            # project
            dpts = gvecToDetectorXY(ghat_c_str.T,
                                    self.rmat, rmat_s, rmat_c,
                                    self.tvec, tvec_s, tvec_c,
                                    beamVec=beam_vec)

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

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

                # back to angles
                tth_eta, gvec_l = detectorXYToGvec(
                    dpts,
                    self.rmat, rmat_s,
                    self.tvec, tvec_s, tvec_c,
                    beamVec=beam_vec)
                tth_eta = np.vstack(tth_eta).T

                # warp measured points
                if self.distortion is not None:
                    if len(self.distortion) == 2:
                        dpts = self.distortion[0](
                            dpts, self.distortion[1],
                            invert=True)
                    else:
                        raise(RuntimeError,
                              "something is wrong with the distortion")

                # plane spacings and energies
                dsp = 1. / rowNorm(gvec_s_str[:, canIntersect].T)
                wlen = 2*dsp*np.sin(0.5*tth_eta[:, 0])

                # clip to detector panel
                _, on_panel = self.clip_to_panel(dpts, buffer_edges=True)

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

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

                # assign output arrays
                xy_det[iG][keepers, :] = dpts[keepers, :]
                hkls_in[iG][:, keepers] = dhkl[:, keepers]
                angles[iG][keepers, :] = tth_eta[keepers, :]
                dspacing[iG, keepers] = dsp[keepers]
                energy[iG, keepers] = ct.keVToAngstrom(wlen[keepers])
                pass    # close conditional on valids
            pass    # close loop on grains
        return xy_det, hkls_in, angles, dspacing, energy
Exemplo n.º 31
0
def latticePlanes(hkls, lparms, ltype='cubic', wavelength=1.54059292, strainMag=None):
    """
    Generates lattice plane data in the direct lattice for a given set
    of Miller indices.  Vector components are written in the
    crystal-relative RHON basis, X. The convention for fixing X to the
    lattice is such that a || x1 and c* || x3, where a and c* are
    direct and reciprocal lattice vectors, respectively.

    USAGE:

    planeInfo = latticePlanes(hkls, lparms, **kwargs)

    INPUTS:

    1) hkls (3 x n float ndarray) is the array of Miller indices for
       the planes of interest.  The vectors are assumed to be
       concatenated along the 1-axis (horizontal).

    2) lparms (1 x m float list) is the array of lattice parameters,
       where m depends on the symmetry group (see below).

    3) The following optional keyword arguments are recognized:

       *) ltype=(string) is a string representing the symmetry type of
          the implied Laue group.  The 11 available choices are shown
          below.  The default value is 'cubic'. Note that each group
          expects a lattice parameter array of the indicated length
          and order.

          latticeType      lparms
          -----------      ------------
          'cubic'          a
          'hexagonal'      a, c
          'trigonal'       a, c
          'rhombohedral'   a, alpha (in degrees)
          'tetragonal'     a, c
          'orthorhombic'   a, b, c
          'monoclinic'     a, b, c, beta (in degrees)
          'triclinic'      a, b, c, alpha, beta, gamma (in degrees)

       *) wavelength=<float> is a value represented the wavelength in
          Angstroms to calculate bragg angles for.  The default value
          is for Cu K-alpha radiation (1.54059292 Angstrom)

       *) strainMag=None

    OUTPUTS:

    1) planeInfo is a dictionary containing the following keys/items:

       normals   (3, n) double array    array of the components to the
                                        unit normals for each {hkl} in
                                        X (horizontally concatenated)

       dspacings (n,  ) double array    array of the d-spacings for
                                        each {hkl}

       2thetas   (n,  ) double array    array of the Bragg angles for
                                        each {hkl} relative to the
                                        specified wavelength

    NOTES:

    *) This function is effectively a wrapper to 'latticeVectors'.
       See 'help(latticeVectors)' for additional info.

    *) Lattice plane d-spacings are calculated from the reciprocal
       lattice vectors specified by {hkl} as shown in Appendix 1 of
       [1].

    REFERENCES:

    [1] B. D. Cullity, ``Elements of X-Ray Diffraction, 2
        ed.''. Addison-Wesley Publishing Company, Inc., 1978. ISBN
        0-201-01174-3

    """
    location = 'latticePlanes'

    assert hkls.shape[0] == 3, "hkls aren't column vectors in call to '%s'!" % (location)

    tag = ltype
    wlen = wavelength

    # get B
    L = latticeVectors(lparms, tag)

    # get G-vectors -- reciprocal vectors in crystal frame
    G = num.dot(L['B'], hkls)

    # magnitudes
    d = 1 / num.sqrt(num.sum(G**2, 0))

    angConv = 1.
    if outputDegrees:
        angConv = r2d
    # two thetas
    tth = angConv * 2 * num.arcsin(wlen / 2 / d)

    p = {'normals':unitVector(G),
         'dspacings':d,
         'tThetas':tth}

    if strainMag is not None:
        p['tThetasLo'] = angConv * 2 * num.arcsin(wlen / 2 / (d*(1.+strainMag)))
        p['tThetasHi'] = angConv * 2 * num.arcsin(wlen / 2 / (d*(1.-strainMag)))

    return p
Exemplo n.º 32
0
def objFuncFitGrain(gFit, gFull, gFlag,
                    instrument,
                    reflections_dict,
                    bMat, wavelength,
                    omePeriod,
                    simOnly=False,
                    return_value_flag=return_value_flag):
    """
    gFull[0]  = expMap_c[0]
    gFull[1]  = expMap_c[1]
    gFull[2]  = expMap_c[2]
    gFull[3]  = tVec_c[0]
    gFull[4]  = tVec_c[1]
    gFull[5]  = tVec_c[2]
    gFull[6]  = vInv_MV[0]
    gFull[7]  = vInv_MV[1]
    gFull[8]  = vInv_MV[2]
    gFull[9]  = vInv_MV[3]
    gFull[10] = vInv_MV[4]
    gFull[11] = vInv_MV[5]

    OLD CALL
    objFuncFitGrain(gFit, gFull, gFlag,
                    detectorParams,
                    xyo_det, hkls_idx, bMat, wavelength,
                    bVec, eVec,
                    dFunc, dParams,
                    omePeriod,
                    simOnly=False, return_value_flag=return_value_flag)
    """

    bVec = instrument.beam_vector
    eVec = instrument.eta_vector

    # fill out parameters
    gFull[gFlag] = gFit

    # map parameters to functional arrays
    rMat_c = xfcapi.makeRotMatOfExpMap(gFull[:3])
    tVec_c = gFull[3:6].reshape(3, 1)
    vInv_s = gFull[6:]
    vMat_s = mutil.vecMVToSymm(vInv_s)  # NOTE: Inverse of V from F = V * R

    # loop over instrument panels
    # CAVEAT: keeping track of key ordering in the "detectors" attribute of
    # instrument here because I am not sure if instatiating them using
    # dict.fromkeys() preserves the same order if using iteration...
    # <JVB 2017-10-31>
    calc_omes_dict = dict.fromkeys(instrument.detectors, [])
    calc_xy_dict = dict.fromkeys(instrument.detectors)
    meas_xyo_all = []
    det_keys_ordered = []
    for det_key, panel in instrument.detectors.iteritems():
        det_keys_ordered.append(det_key)

        rMat_d, tVec_d, chi, tVec_s = extract_detector_transformation(
            instrument.detector_parameters[det_key])

        results = reflections_dict[det_key]
        if len(results) == 0:
            continue

        """
        extract data from results list fields:
          refl_id, gvec_id, hkl, sum_int, max_int, pred_ang, meas_ang, meas_xy

        or array from spots tables:
          0:5    ID    PID    H    K    L       
          5:7    sum(int)    max(int)      
          7:10   pred tth    pred eta    pred ome                 
          10:13  meas tth    meas eta    meas ome                 
          13:15  pred X    pred Y                   
          15:17  meas X    meas Y                 
        """
        if isinstance(results, list):
            # WARNING: hkls and derived vectors below must be columnwise;
            # strictly necessary??? change affected APIs instead?
            # <JVB 2017-03-26>
            hkls = np.atleast_2d(
                np.vstack([x[2] for x in results])
            ).T
            
            meas_xyo = np.atleast_2d(
                np.vstack([np.r_[x[7], x[6][-1]] for x in results])
            )
        elif isinstance(results, np.ndarray):
            hkls = np.atleast_2d(results[:, 2:5]).T
            meas_xyo = np.atleast_2d(results[:, [15, 16, 12]])

        # FIXME: distortion handling must change to class-based
        if panel.distortion is not None:
            meas_omes = meas_xyo[:, 2]
            xy_unwarped = panel.distortion[0](
                    meas_xyo[:, :2], panel.distortion[1])
            meas_xyo = np.vstack([xy_unwarped.T, meas_omes]).T
            pass

        # append to meas_omes
        meas_xyo_all.append(meas_xyo)

        # G-vectors:
        #   1. calculate full g-vector components in CRYSTAL frame from B
        #   2. rotate into SAMPLE frame and apply stretch
        #   3. rotate back into CRYSTAL frame and normalize to unit magnitude
        # IDEA: make a function for this sequence of operations with option for
        # choosing ouput frame (i.e. CRYSTAL vs SAMPLE vs LAB)
        gVec_c = np.dot(bMat, hkls)
        gVec_s = np.dot(vMat_s, np.dot(rMat_c, gVec_c))
        gHat_c = mutil.unitVector(np.dot(rMat_c.T, gVec_s))

        # !!!: check that this operates on UNWARPED xy
        match_omes, calc_omes = matchOmegas(
            meas_xyo, hkls, chi, rMat_c, bMat, wavelength,
            vInv=vInv_s, beamVec=bVec, etaVec=eVec,
            omePeriod=omePeriod)

        # append to omes dict
        calc_omes_dict[det_key] = calc_omes

        # TODO: try Numba implementations
        rMat_s = xfcapi.makeOscillRotMatArray(chi, calc_omes)
        calc_xy = xfcapi.gvecToDetectorXYArray(gHat_c.T,
                                               rMat_d, rMat_s, rMat_c,
                                               tVec_d, tVec_s, tVec_c,
                                               beamVec=bVec)

        # append to xy dict
        calc_xy_dict[det_key] = calc_xy
        pass

    # stack results to concatenated arrays
    calc_omes_all = np.hstack([calc_omes_dict[k] for k in det_keys_ordered])
    tmp = []
    for k in det_keys_ordered:
        if calc_xy_dict[k] is not None:
            tmp.append(calc_xy_dict[k])
    calc_xy_all = np.vstack(tmp)
    meas_xyo_all = np.vstack(meas_xyo_all)

    npts = len(meas_xyo_all)
    if np.any(np.isnan(calc_xy)):
        raise RuntimeError(
            "infeasible pFull: may want to scale" +
            "back finite difference step size")

    # return values
    if simOnly:
        # return simulated values
        if return_value_flag in [None, 1]:
            retval = np.hstack([calc_xy_all, calc_omes_all.reshape(npts, 1)])
        else:
            rd = dict.fromkeys(det_keys_ordered)
            for det_key in det_keys_ordered:
                rd[det_key] = {'calc_xy': calc_xy_dict[det_key],
                               'calc_omes': calc_omes_dict[det_key]}
            retval = rd
    else:
        # return residual vector
        # IDEA: try angles instead of xys?
        diff_vecs_xy = calc_xy_all - meas_xyo_all[:, :2]
        diff_ome = xf.angularDifference(calc_omes_all, meas_xyo_all[:, 2])
        retval = np.hstack([diff_vecs_xy,
                            diff_ome.reshape(npts, 1)
                            ]).flatten()
        if return_value_flag == 1:
            # return scalar sum of squared residuals
            retval = sum(abs(retval))
        elif return_value_flag == 2:
            # return DOF-normalized chisq
            # TODO: check this calculation
            denom = 3*npts - len(gFit) - 1.
            if denom != 0:
                nu_fac = 1. / denom
            else:
                nu_fac = 1.
            retval = nu_fac * sum(retval**2)
    return retval
Exemplo n.º 33
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
Exemplo n.º 34
0
    def simulate_laue_pattern(self,
                              crystal_data,
                              minEnergy=5.,
                              maxEnergy=35.,
                              rmat_s=None,
                              tvec_s=None,
                              grain_params=None,
                              beam_vec=None):
        """
        """
        if isinstance(crystal_data, PlaneData):

            plane_data = crystal_data

            # grab the expanded list of hkls from plane_data
            hkls = np.hstack(plane_data.getSymHKLs())

            # and the unit plane normals (G-vectors) in CRYSTAL FRAME
            gvec_c = np.dot(plane_data.latVecOps['B'], hkls)
        elif len(crystal_data) == 2:
            # !!! should clean this up
            hkls = np.array(crystal_data[0])
            bmat = crystal_data[1]
            gvec_c = np.dot(bmat, hkls)
        else:
            raise (RuntimeError, 'argument list not understood')
        nhkls_tot = hkls.shape[1]

        # parse energy ranges
        # TODO: allow for spectrum parsing
        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(ct.keVToAngstrom(maxEnergy[i]))
                lmax.append(ct.keVToAngstrom(minEnergy[i]))
        else:
            lmin = ct.keVToAngstrom(maxEnergy)
            lmax = ct.keVToAngstrom(minEnergy)

        # parse grain parameters kwarg
        if grain_params is None:
            grain_params = np.atleast_2d(
                np.hstack([np.zeros(6), ct.identity_6x1]))
        n_grains = len(grain_params)

        # sample rotation
        if rmat_s is None:
            rmat_s = ct.identity_3x3

        # dummy translation vector... make input
        if tvec_s is None:
            tvec_s = ct.zeros_3

        # beam vector
        if beam_vec is None:
            beam_vec = ct.beam_vec

        # =========================================================================
        # LOOP OVER GRAINS
        # =========================================================================

        # 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))
        for iG, gp in enumerate(grain_params):
            rmat_c = 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
            gvec_s_str = np.dot(vInv_s, np.dot(rmat_c, gvec_c))
            ghat_c_str = mutil.unitVector(np.dot(rmat_c.T, gvec_s_str))

            # project
            dpts = gvecToDetectorXY(ghat_c_str.T,
                                    self.rmat,
                                    rmat_s,
                                    rmat_c,
                                    self.tvec,
                                    tvec_s,
                                    tvec_c,
                                    beamVec=beam_vec)

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

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

                # back to angles
                tth_eta, gvec_l = detectorXYToGvec(dpts,
                                                   self.rmat,
                                                   rmat_s,
                                                   self.tvec,
                                                   tvec_s,
                                                   tvec_c,
                                                   beamVec=beam_vec)
                tth_eta = np.vstack(tth_eta).T

                # warp measured points
                if self.distortion is not None:
                    if len(self.distortion) == 2:
                        dpts = self.distortion[0](dpts,
                                                  self.distortion[1],
                                                  invert=True)
                    else:
                        raise (RuntimeError,
                               "something is wrong with the distortion")

                # plane spacings and energies
                dsp = 1. / rowNorm(gvec_s_str[:, canIntersect].T)
                wlen = 2 * dsp * np.sin(0.5 * tth_eta[:, 0])

                # clip to detector panel
                _, on_panel = self.clip_to_panel(dpts, buffer_edges=True)

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

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

                # assign output arrays
                xy_det[iG][keepers, :] = dpts[keepers, :]
                hkls_in[iG][:, keepers] = dhkl[:, keepers]
                angles[iG][keepers, :] = tth_eta[keepers, :]
                dspacing[iG, keepers] = dsp[keepers]
                energy[iG, keepers] = ct.keVToAngstrom(wlen[keepers])
                pass  # close conditional on valids
            pass  # close loop on grains
        return xy_det, hkls_in, angles, dspacing, energy
Exemplo n.º 35
0
def find_orientations(cfg, hkls=None, clean=False, profile=False):
    """
    Takes a config dict as input, generally a yml document

    NOTE: single cfg instance, not iterator!
    """

    # ...make this an attribute in cfg?
    analysis_id = '%s_%s' %(
        cfg.analysis_name.strip().replace(' ', '-'),
        cfg.material.active.strip().replace(' ', '-'),
        )

    # grab planeData object
    matl = cPickle.load(open('materials.cpl', 'r'))
    md = dict(zip([matl[i].name for i in range(len(matl))], matl))
    pd = md[cfg.material.active].planeData

    # make image_series
    image_series = cfg.image_series.omegaseries

    # need instrument cfg later on down...
    instr_cfg = get_instrument_parameters(cfg)
    detector_params = np.hstack([
        instr_cfg['detector']['transform']['tilt_angles'],
        instr_cfg['detector']['transform']['t_vec_d'],
        instr_cfg['oscillation_stage']['chi'],
        instr_cfg['oscillation_stage']['t_vec_s'],
        ])
    rdim = cfg.instrument.detector.pixels.size[0]*cfg.instrument.detector.pixels.rows
    cdim = cfg.instrument.detector.pixels.size[1]*cfg.instrument.detector.pixels.columns
    panel_dims = ((-0.5*cdim, -0.5*rdim),
                  ( 0.5*cdim,  0.5*rdim),
                  )
    # UGH! hard-coded distortion...
    if instr_cfg['detector']['distortion']['function_name'] == 'GE_41RT':
        distortion = (dFuncs.GE_41RT,
                      instr_cfg['detector']['distortion']['parameters'],
                      )
    else:
        distortion = None

    min_compl = cfg.find_orientations.clustering.completeness

    # start logger
    logger.info("beginning analysis '%s'", cfg.analysis_name)

    # load the eta_ome orientation maps
    eta_ome = load_eta_ome_maps(cfg, pd, image_series, hkls=hkls, clean=clean)

    ome_range = (
        np.min(eta_ome.omeEdges),
        np.max(eta_ome.omeEdges)
        )
    try:
        # are we searching the full grid of orientation space?
        qgrid_f = cfg.find_orientations.use_quaternion_grid
        quats = np.load(qgrid_f)
        logger.info("Using %s for full quaternion search", qgrid_f)
        hkl_ids = None
    except (IOError, ValueError, AttributeError):
        # or doing a seeded search?
        logger.info("Defaulting to seeded search")
        hkl_seeds = cfg.find_orientations.seed_search.hkl_seeds
        hkl_ids = [
            eta_ome.planeData.hklDataList[i]['hklID'] for i in hkl_seeds
        ]
        hklseedstr = ', '.join(
            [str(i) for i in eta_ome.planeData.hkls.T[hkl_seeds]]
            )
        logger.info(
            "Seeding search using hkls from %s: %s",
            cfg.find_orientations.orientation_maps.file,
            hklseedstr
            )
        quats = generate_orientation_fibers(
            eta_ome,
            detector_params[6],
            cfg.find_orientations.threshold,
            cfg.find_orientations.seed_search.hkl_seeds,
            cfg.find_orientations.seed_search.fiber_ndiv,
            ncpus=cfg.multiprocessing,
            )
        if save_as_ascii:
            np.savetxt(
                os.path.join(cfg.working_dir, 'trial_orientations.dat'),
                quats.T,
                fmt="%.18e",
                delimiter="\t"
                )
            pass
        pass # close conditional on grid search
    
    # generate the completion maps
    logger.info("Running paintgrid on %d trial orientations", quats.shape[1])
    if profile:
        logger.info("Profiling mode active, forcing ncpus to 1")
        ncpus = 1
    else:
        ncpus = cfg.multiprocessing
        logger.info(
            "%d of %d available processors requested", ncpus, mp.cpu_count()
            )
    compl = idx.paintGrid(
        quats,
        eta_ome,
        etaRange=np.radians(cfg.find_orientations.eta.range),
        omeTol=np.radians(cfg.find_orientations.omega.tolerance),
        etaTol=np.radians(cfg.find_orientations.eta.tolerance),
        omePeriod=np.radians(cfg.find_orientations.omega.period),
        threshold=cfg.find_orientations.threshold,
        doMultiProc=ncpus > 1,
        nCPUs=ncpus
        )

    if save_as_ascii:
        np.savetxt(os.path.join(cfg.working_dir, 'completeness.dat'), compl)
    else:
        np.save(
            os.path.join(
                cfg.working_dir,
                'scored_orientations_%s.npy' %analysis_id
                ),
            np.vstack([quats, compl])
            )

    ##########################################################
    ##   Simulate N random grains to get neighborhood size  ##
    ##########################################################
    if hkl_ids is not None:
        ngrains = 100
        rand_q = mutil.unitVector(np.random.randn(4, ngrains))
        rand_e = np.tile(2.*np.arccos(rand_q[0, :]), (3, 1)) \
          * mutil.unitVector(rand_q[1:, :])
        refl_per_grain = np.zeros(ngrains)
        num_seed_refls = np.zeros(ngrains)
        print('fo: hklids = ', hkl_ids)
        for i in range(ngrains):
            grain_params = np.hstack([rand_e[:, i],
                                      xf.zeroVec.flatten(),
                                      xf.vInv_ref.flatten()
                                      ])
            sim_results = simulateGVecs(pd,
                                        detector_params,
                                        grain_params,
                                        ome_range=(ome_range,),
                                        ome_period=(ome_range[0], ome_range[0]+2*np.pi),
                                        eta_range=np.radians(cfg.find_orientations.eta.range),
                                        panel_dims=panel_dims,
                                        pixel_pitch=cfg.instrument.detector.pixels.size,
                                        distortion=distortion,
                                        )
            refl_per_grain[i] = len(sim_results[0])
            # lines below fix bug when sim_results[0] is empty
            if refl_per_grain[i] > 0:
                num_seed_refls[i] = np.sum([sum(sim_results[0] == hkl_id) for hkl_id in hkl_ids])
            else:
                num_seed_refls[i] = 0
        #min_samples = 2
        min_samples = max(
            int(np.floor(0.5*min_compl*min(num_seed_refls))),
            2
            )
        mean_rpg = int(np.round(np.average(refl_per_grain)))
    else:
        min_samples = 1
        mean_rpg = 1

    logger.info("mean number of reflections per grain is %d", mean_rpg)
    logger.info("neighborhood size estimate is %d points", min_samples)

    # cluster analysis to identify orientation blobs, the final output:
    qbar, cl = run_cluster(compl, quats, pd.getQSym(), cfg, min_samples=min_samples)

    analysis_id = '%s_%s' %(
        cfg.analysis_name.strip().replace(' ', '-'),
        cfg.material.active.strip().replace(' ', '-'),
        )

    np.savetxt(
        os.path.join(
            cfg.working_dir,
            'accepted_orientations_%s.dat' %analysis_id
            ),
        qbar.T,
        fmt="%.18e",
        delimiter="\t")

    return
Exemplo n.º 36
0
Zl = np.c_[0, 0, 1].T

eVec = Xl.flatten()

chi_b = 15
ome_b = 5
rMat_b = np.dot(rot.rotMatOfExpMap(d2r * chi_b * Xl),
                rot.rotMatOfExpMap(d2r * ome_b * Yl))
bVec = np.dot(rMat_b, -Zl)
beam_len = 10

tVec_d = np.c_[-5.0, 3.0, -10.0].T
tVec_s = np.c_[3.0, 0.2, -1.5].T
tVec_c = np.c_[2.0, 0.8, -0.7].T

rMat_d = rot.rotMatOfExpMap(d2r * 21 * mutil.unitVector(np.c_[2, 3, 1].T))

chi = 21 * d2r
ome = 67 * d2r
rMat_s = np.dot(rot.rotMatOfExpMap(chi * Xl), rot.rotMatOfExpMap(ome * Yl))

rMat_c = rot.rotMatOfExpMap(d2r * 36 * mutil.unitVector(np.c_[1, 2, 3].T))

det_size = (6, 4)
det_pt = (-1.15, 0.875)


def gen_sk(fname, det_size, det_pt, eVec, beam_len, bVec, rMat_b, rMat_d,
           rMat_s, rMat_c, tVec_d, tVec_s, tVec_c):
    if isinstance(fname, file):
        fid = f
Exemplo n.º 37
0
def mockup_experiment():
    # user options
    # each grain is provided in the form of a quaternion.

    # The following array contains the quaternions for the array. Note that the
    # quaternions are in the columns, with the first row (row 0) being the real
    # part w. We assume that we are dealing with unit quaternions

    quats = np.array([[0.91836393, 0.90869942], [0.33952917, 0.1834835],
                      [0.17216207, 0.10095837], [0.10811041, 0.36111851]])

    n_grains = quats.shape[-1]  # last dimension provides the number of grains
    phis = 2. * np.arccos(
        quats[0, :])  # phis are the angles for the quaternion
    ns = mutil.unitVector(
        quats[1:, :])  # ns contains the rotation axis as an unit vector
    exp_maps = np.array([phis[i] * ns[:, i] for i in range(n_grains)])
    rMat_c = rot.rotMatOfQuat(quats)

    cvec = np.arange(-25, 26)
    X, Y, Z = np.meshgrid(cvec, cvec, cvec)

    crd0 = 1e-3 * np.vstack([X.flatten(), Y.flatten(), Z.flatten()]).T
    crd1 = crd0 + np.r_[0.100, 0.100, 0]
    crds = np.array([crd0, crd1])

    # make grain parameters
    grain_params = []
    for i in range(n_grains):
        for j in range(len(crd0)):
            grain_params.append(
                np.hstack(
                    [exp_maps[i, :], crds[i][j, :],
                     xf.vInv_ref.flatten()]))

    # scan range and period
    ome_period = (0, 2 * np.pi)
    ome_range = [
        ome_period,
    ]
    ome_step = np.radians(1.)
    nframes = 0
    for i in range(len(ome_range)):
        del_ome = ome_range[i][1] - ome_range[i][0]
        nframes += int((ome_range[i][1] - ome_range[i][0]) / ome_step)

    ome_edges = np.arange(nframes + 1) * ome_step

    # instrument
    with open('./retiga.yml', 'r') as fildes:
        instr_cfg = yaml.load(fildes)

    tiltAngles = instr_cfg['detector']['transform']['tilt_angles']
    tVec_d = np.array(instr_cfg['detector']['transform']['t_vec_d']).reshape(
        3, 1)
    chi = instr_cfg['oscillation_stage']['chi']
    tVec_s = np.array(instr_cfg['oscillation_stage']['t_vec_s']).reshape(3, 1)
    rMat_d = xfcapi.makeDetectorRotMat(tiltAngles)
    rMat_s = xfcapi.makeOscillRotMat([chi, 0.])

    pixel_size = instr_cfg['detector']['pixels']['size']
    nrows = instr_cfg['detector']['pixels']['rows']
    ncols = instr_cfg['detector']['pixels']['columns']

    col_ps = pixel_size[1]
    row_ps = pixel_size[0]

    row_dim = row_ps * nrows  # in mm
    col_dim = col_ps * ncols  # in mm
    panel_dims = [(-0.5 * ncols * col_ps, -0.5 * nrows * row_ps),
                  (0.5 * ncols * col_ps, 0.5 * nrows * row_ps)]

    x_col_edges = col_ps * (np.arange(ncols + 1) - 0.5 * ncols)
    y_row_edges = row_ps * (np.arange(nrows, -1, -1) - 0.5 * nrows)
    #x_col_edges = np.arange(panel_dims[0][0], panel_dims[1][0] + 0.5*col_ps, col_ps)
    #y_row_edges = np.arange(panel_dims[0][1], panel_dims[1][1] + 0.5*row_ps, row_ps)
    rx, ry = np.meshgrid(x_col_edges, y_row_edges)

    gcrds = xfcapi.detectorXYToGvec(
        np.vstack([rx.flatten(), ry.flatten()]).T, rMat_d, rMat_s, tVec_d,
        tVec_s, np.zeros(3))

    max_pixel_tth = np.amax(gcrds[0][0])
    detector_params = np.hstack(
        [tiltAngles, tVec_d.flatten(), chi,
         tVec_s.flatten()])
    distortion = None

    # a different parametrization for the sensor (makes for faster quantization)
    base = np.array([x_col_edges[0], y_row_edges[0], ome_edges[0]])
    deltas = np.array([
        x_col_edges[1] - x_col_edges[0], y_row_edges[1] - y_row_edges[0],
        ome_edges[1] - ome_edges[0]
    ])
    inv_deltas = 1.0 / deltas
    clip_vals = np.array([ncols, nrows])

    # dilation
    max_diameter = np.sqrt(3) * 0.005
    row_dilation = np.ceil(0.5 * max_diameter / row_ps)
    col_dilation = np.ceil(0.5 * max_diameter / col_ps)

    # crystallography data
    from hexrd import valunits
    gold = material.Material('gold')
    gold.sgnum = 225
    gold.latticeParameters = [
        4.0782,
    ]
    gold.hklMax = 200
    gold.beamEnergy = valunits.valWUnit("wavelength", "ENERGY", 52, "keV")
    gold.planeData.exclusions = None
    gold.planeData.tThMax = max_pixel_tth  #note this comes from info in the detector

    ns = argparse.Namespace()
    # grains related information
    ns.n_grains = n_grains  # this can be derived from other values...
    ns.rMat_c = rMat_c  # n_grains rotation matrices (one per grain)
    ns.exp_maps = exp_maps  # n_grains exp_maps -angle * rotation axis- (one per grain)

    ns.plane_data = gold.planeData
    ns.detector_params = detector_params
    ns.pixel_size = pixel_size
    ns.ome_range = ome_range
    ns.ome_period = ome_period
    ns.x_col_edges = x_col_edges
    ns.y_row_edges = y_row_edges
    ns.ome_edges = ome_edges
    ns.ncols = ncols
    ns.nrows = nrows
    ns.nframes = nframes  # used only in simulate...
    ns.rMat_d = rMat_d
    ns.tVec_d = tVec_d
    ns.chi = chi  # note this is used to compute S... why is it needed?
    ns.tVec_s = tVec_s
    # ns.rMat_s = rMat_s
    # ns.tVec_s = tVec_s
    ns.rMat_c = rMat_c
    ns.row_dilation = row_dilation
    ns.col_dilation = col_dilation
    ns.distortion = distortion
    ns.panel_dims = panel_dims  # used only in simulate...
    ns.base = base
    ns.inv_deltas = inv_deltas
    ns.clip_vals = clip_vals

    return grain_params, ns
Exemplo n.º 38
0
rmats_final = rot.rotMatOfExpMap(np.array(expmaps_final)[:, grainlist])

# getting symmetry group directly here; could also grab from planeData object
# qsym = symm.quatOfLaueGroup('d6h')
plane_data = load_pdata(
    '/Users/rachellim/Documents/Research/CHESS_Jun17/2020-08-03/materials2.hexrd',
    'ti7al')
qsym = plane_data.getQSym()
bmat = plane_data.latVecOps['B']

# this was for 001 triangle
# sst_vertices = mutil.unitVector(matfuncs.triu(np.ones((3, 3))).T)
# this if for the standard triangle
# sst_vertices = mutil.unitVector(matfuncs.triu(np.ones((3, 3))))
sst_vertices = mutil.unitVector(
    np.dot(bmat,
           np.array([[0, 0, 1], [2, -1, 0], [1, 0, 0]]).T))
sst_normals = np.array([
    np.cross(sst_vertices[:, i[0]], sst_vertices[:, i[1]])
    for i in [(0, 1), (1, 2), (2, 0)]
]).T

# DEFINE SAMPLE DIRECTION YOU WANT FOR IPF THEN MOVE THE CRYSTAL FRAME
s = mutil.unitVector(np.c_[0., 1., 0.].T)  # sample Y a.k.a. loading
s_c_init = np.zeros((len(rmats_init), 3))
for i, rm in enumerate(rmats_init):
    s_c_init[i] = np.dot(rm.T, s).flatten()

# APPLY SYMMETRIES AND PICK REPRESENTATIVE IN SPECIFED SST
sst_list = []
csym_init = []
Exemplo n.º 39
0
def create_clustering_parameters(cfg, eta_ome):
    """
    Compute min samples and mean reflections per grain for clustering

    Parameters
    ----------
    cfg : TYPE
        DESCRIPTION.
    eta_ome : TYPE
        DESCRIPTION.

    Returns
    -------
    Tuple of (min_samples, mean_rpg)

    """

    # grab objects from config
    plane_data = cfg.material.plane_data
    imsd = cfg.image_series
    instr = cfg.instrument.hedm
    eta_ranges = cfg.find_orientations.eta.range
    compl_thresh = cfg.find_orientations.clustering.completeness

    # handle omega period
    ome_period, ome_ranges = _process_omegas(imsd)

    active_hkls = cfg.find_orientations.orientation_maps.active_hkls \
        or eta_ome.iHKLList

    fiber_seeds = cfg.find_orientations.seed_search.hkl_seeds

    # Simulate N random grains to get neighborhood size
    seed_hkl_ids = [
        plane_data.hklDataList[active_hkls[i]]['hklID'] for i in fiber_seeds
    ]

    # !!! default to use 100 grains
    ngrains = 100
    rand_q = mutil.unitVector(np.random.randn(4, ngrains))
    rand_e = np.tile(2.*np.arccos(rand_q[0, :]), (3, 1)) \
        * mutil.unitVector(rand_q[1:, :])
    grain_param_list = np.vstack([
        rand_e,
        np.zeros((3, ngrains)),
        np.tile(const.identity_6x1, (ngrains, 1)).T
    ]).T
    sim_results = instr.simulate_rotation_series(
        plane_data,
        grain_param_list,
        eta_ranges=np.radians(eta_ranges),
        ome_ranges=np.radians(ome_ranges),
        ome_period=np.radians(ome_period))

    refl_per_grain = np.zeros(ngrains)
    seed_refl_per_grain = np.zeros(ngrains)
    for sim_result in sim_results.values():
        for i, refl_ids in enumerate(sim_result[0]):
            refl_per_grain[i] += len(refl_ids)
            seed_refl_per_grain[i] += np.sum(
                [sum(refl_ids == hkl_id) for hkl_id in seed_hkl_ids])

    min_samples = max(
        int(np.floor(0.5 * compl_thresh * min(seed_refl_per_grain))), 2)
    mean_rpg = int(np.round(np.average(refl_per_grain)))

    return min_samples, mean_rpg
Exemplo n.º 40
0
def latticePlanes(hkls, lparms, ltype="cubic", wavelength=1.54059292, strainMag=None):
    """
    Generates lattice plane data in the direct lattice for a given set
    of Miller indices.  Vector components are written in the
    crystal-relative RHON basis, X. The convention for fixing X to the
    lattice is such that a || x1 and c* || x3, where a and c* are
    direct and reciprocal lattice vectors, respectively.

    USAGE:

    planeInfo = latticePlanes(hkls, lparms, **kwargs)

    INPUTS:

    1) hkls (3 x n float ndarray) is the array of Miller indices for
       the planes of interest.  The vectors are assumed to be
       concatenated along the 1-axis (horizontal).

    2) lparms (1 x m float list) is the array of lattice parameters,
       where m depends on the symmetry group (see below).

    3) The following optional keyword arguments are recognized:

       *) ltype=(string) is a string representing the symmetry type of
          the implied Laue group.  The 11 available choices are shown
          below.  The default value is 'cubic'. Note that each group
          expects a lattice parameter array of the indicated length
          and order.

          latticeType      lparms
          -----------      ------------
          'cubic'          a
          'hexagonal'      a, c
          'trigonal'       a, c
          'rhombohedral'   a, alpha (in degrees)
          'tetragonal'     a, c
          'orthorhombic'   a, b, c
          'monoclinic'     a, b, c, beta (in degrees)
          'triclinic'      a, b, c, alpha, beta, gamma (in degrees)

       *) wavelength=<float> is a value represented the wavelength in
          Angstroms to calculate bragg angles for.  The default value
          is for Cu K-alpha radiation (1.54059292 Angstrom)

       *) strainMag=None

    OUTPUTS:

    1) planeInfo is a dictionary containing the following keys/items:

       normals   (3, n) double array    array of the components to the
                                        unit normals for each {hkl} in
                                        X (horizontally concatenated)

       dspacings (n,  ) double array    array of the d-spacings for
                                        each {hkl}

       2thetas   (n,  ) double array    array of the Bragg angles for
                                        each {hkl} relative to the
                                        specified wavelength

    NOTES:

    *) This function is effectively a wrapper to 'latticeVectors'.
       See 'help(latticeVectors)' for additional info.

    *) Lattice plane d-spacings are calculated from the reciprocal
       lattice vectors specified by {hkl} as shown in Appendix 1 of
       [1].

    REFERENCES:

    [1] B. D. Cullity, ``Elements of X-Ray Diffraction, 2
        ed.''. Addison-Wesley Publishing Company, Inc., 1978. ISBN
        0-201-01174-3

    """
    location = "latticePlanes"

    assert hkls.shape[0] == 3, "hkls aren't column vectors in call to '%s'!" % (location)

    tag = ltype
    wlen = wavelength

    # get B
    L = latticeVectors(lparms, tag)

    # get G-vectors -- reciprocal vectors in crystal frame
    G = num.dot(L["B"], hkls)

    # magnitudes
    d = 1 / num.sqrt(num.sum(G ** 2, 0))

    angConv = 1.0
    if outputDegrees:
        angConv = r2d
    # two thetas
    tth = angConv * 2 * num.arcsin(wlen / 2 / d)

    p = {"normals": unitVector(G), "dspacings": d, "tThetas": tth}

    if strainMag is not None:
        p["tThetasLo"] = angConv * 2 * num.arcsin(wlen / 2 / (d * (1.0 + strainMag)))
        p["tThetasHi"] = angConv * 2 * num.arcsin(wlen / 2 / (d * (1.0 - strainMag)))

    return p
Exemplo n.º 41
0
def objFuncFitGrain(gFit, gFull, gFlag,
                    detectorParams,
                    xyo_det, hkls_idx, bMat, wavelength,
                    bVec, eVec,
                    dFunc, dParams,
                    omePeriod,
                    simOnly=False, returnScalarValue=returnScalarValue):
    """
    gFull[0]  = expMap_c[0]
    gFull[1]  = expMap_c[1]
    gFull[2]  = expMap_c[2]
    gFull[3]  = tVec_c[0]
    gFull[4]  = tVec_c[1]
    gFull[5]  = tVec_c[2]
    gFull[6]  = vInv_MV[0]
    gFull[7]  = vInv_MV[1]
    gFull[8]  = vInv_MV[2]
    gFull[9]  = vInv_MV[3]
    gFull[10] = vInv_MV[4]
    gFull[11] = vInv_MV[5]

    detectorParams[0]  = tiltAngles[0]
    detectorParams[1]  = tiltAngles[1]
    detectorParams[2]  = tiltAngles[2]
    detectorParams[3]  = tVec_d[0]
    detectorParams[4]  = tVec_d[1]
    detectorParams[5]  = tVec_d[2]
    detectorParams[6]  = chi
    detectorParams[7]  = tVec_s[0]
    detectorParams[8]  = tVec_s[1]
    detectorParams[9]  = tVec_s[2]
    """
    npts   = len(xyo_det)

    gFull[gFlag] = gFit

    xy_unwarped = dFunc(xyo_det[:, :2], dParams)

    rMat_d = xfcapi.makeDetectorRotMat(detectorParams[:3])
    tVec_d = detectorParams[3:6].reshape(3, 1)
    chi    = detectorParams[6]
    tVec_s = detectorParams[7:10].reshape(3, 1)

    rMat_c = xfcapi.makeRotMatOfExpMap(gFull[:3])
    tVec_c = gFull[3:6].reshape(3, 1)
    vInv_s = gFull[6:]
    vMat_s = mutil.vecMVToSymm(vInv_s)              # NOTE: Inverse of V from F = V * R

    gVec_c = np.dot(bMat, hkls_idx)                 # gVecs with magnitudes in CRYSTAL frame
    gVec_s = np.dot(vMat_s, np.dot(rMat_c, gVec_c)) # stretched gVecs in SAMPLE frame
    gHat_c = mutil.unitVector(
        np.dot(rMat_c.T, gVec_s)) # unit reciprocal lattice vectors in CRYSTAL frame

    match_omes, calc_omes = matchOmegas(xyo_det, hkls_idx, chi, rMat_c, bMat, wavelength,
                                        vInv=vInv_s, beamVec=bVec, etaVec=eVec,
                                        omePeriod=omePeriod)

    calc_xy = np.zeros((npts, 2))
    for i in range(npts):
        rMat_s = xfcapi.makeOscillRotMat([chi, calc_omes[i]])
        calc_xy[i, :] = xfcapi.gvecToDetectorXY(gHat_c[:, i],
                                                rMat_d, rMat_s, rMat_c,
                                                tVec_d, tVec_s, tVec_c,
                                                beamVec=bVec).flatten()
        pass
    if np.any(np.isnan(calc_xy)):
        print "infeasible pFull"

    # return values
    if simOnly:
        retval = np.hstack([calc_xy, calc_omes.reshape(npts, 1)])
    else:
        diff_vecs_xy = calc_xy - xy_unwarped[:, :2]
        diff_ome     = xf.angularDifference( calc_omes, xyo_det[:, 2] )
        retval = mutil.rowNorm(
            np.hstack([diff_vecs_xy,
                       diff_ome.reshape(npts, 1)
                       ]) ).flatten()
        if returnScalarValue:
            retval = sum( retval )
    return retval
Exemplo n.º 42
0
def objFuncFitGrain(gFit,
                    gFull,
                    gFlag,
                    detectorParams,
                    xyo_det,
                    hkls_idx,
                    bMat,
                    wavelength,
                    bVec,
                    eVec,
                    dFunc,
                    dParams,
                    omePeriod,
                    simOnly=False,
                    return_value_flag=return_value_flag):
    """
    gFull[0]  = expMap_c[0]
    gFull[1]  = expMap_c[1]
    gFull[2]  = expMap_c[2]
    gFull[3]  = tVec_c[0]
    gFull[4]  = tVec_c[1]
    gFull[5]  = tVec_c[2]
    gFull[6]  = vInv_MV[0]
    gFull[7]  = vInv_MV[1]
    gFull[8]  = vInv_MV[2]
    gFull[9]  = vInv_MV[3]
    gFull[10] = vInv_MV[4]
    gFull[11] = vInv_MV[5]

    detectorParams[0]  = tiltAngles[0]
    detectorParams[1]  = tiltAngles[1]
    detectorParams[2]  = tiltAngles[2]
    detectorParams[3]  = tVec_d[0]
    detectorParams[4]  = tVec_d[1]
    detectorParams[5]  = tVec_d[2]
    detectorParams[6]  = chi
    detectorParams[7]  = tVec_s[0]
    detectorParams[8]  = tVec_s[1]
    detectorParams[9]  = tVec_s[2]
    """
    npts = len(xyo_det)

    gFull[gFlag] = gFit

    xy_unwarped = dFunc(xyo_det[:, :2], dParams)

    rMat_d = xfcapi.makeDetectorRotMat(detectorParams[:3])
    tVec_d = detectorParams[3:6].reshape(3, 1)
    chi = detectorParams[6]
    tVec_s = detectorParams[7:10].reshape(3, 1)

    rMat_c = xfcapi.makeRotMatOfExpMap(gFull[:3])
    tVec_c = gFull[3:6].reshape(3, 1)
    vInv_s = gFull[6:]
    vMat_s = mutil.vecMVToSymm(vInv_s)  # NOTE: Inverse of V from F = V * R

    gVec_c = np.dot(bMat, hkls_idx)  # gVecs with magnitudes in CRYSTAL frame
    gVec_s = np.dot(vMat_s, np.dot(rMat_c,
                                   gVec_c))  # stretched gVecs in SAMPLE frame
    gHat_c = mutil.unitVector(np.dot(
        rMat_c.T, gVec_s))  # unit reciprocal lattice vectors in CRYSTAL frame

    match_omes, calc_omes = matchOmegas(xyo_det,
                                        hkls_idx,
                                        chi,
                                        rMat_c,
                                        bMat,
                                        wavelength,
                                        vInv=vInv_s,
                                        beamVec=bVec,
                                        etaVec=eVec,
                                        omePeriod=omePeriod)

    rMat_s = xfcapi.makeOscillRotMatArray(chi, calc_omes)
    calc_xy = xfcapi.gvecToDetectorXYArray(gHat_c.T,
                                           rMat_d,
                                           rMat_s,
                                           rMat_c,
                                           tVec_d,
                                           tVec_s,
                                           tVec_c,
                                           beamVec=bVec)

    if np.any(np.isnan(calc_xy)):
        print "infeasible pFull"

    # return values
    if simOnly:
        retval = np.hstack([calc_xy, calc_omes.reshape(npts, 1)])
    else:
        diff_vecs_xy = calc_xy - xy_unwarped[:, :2]
        diff_ome = xf.angularDifference(calc_omes, xyo_det[:, 2])
        retval = np.hstack([diff_vecs_xy, diff_ome.reshape(npts, 1)]).flatten()
        if return_value_flag == 1:
            retval = sum(abs(retval))
        elif return_value_flag == 2:
            denom = npts - len(gFit) - 1.
            if denom != 0:
                nu_fac = 1. / denom
            else:
                nu_fac = 1.
            retval = nu_fac * sum(retval**2 / abs(
                np.hstack([calc_xy, calc_omes.reshape(npts, 1)]).flatten()))
    return retval
Exemplo n.º 43
0
def find_orientations(cfg, hkls=None, clean=False, profile=False):
    """
    Takes a config dict as input, generally a yml document

    NOTE: single cfg instance, not iterator!
    """

    # ...make this an attribute in cfg?
    analysis_id = '%s_%s' % (
        cfg.analysis_name.strip().replace(' ', '-'),
        cfg.material.active.strip().replace(' ', '-'),
    )

    # grab planeData object
    matl = cPickle.load(open('materials.cpl', 'r'))
    md = dict(zip([matl[i].name for i in range(len(matl))], matl))
    pd = md[cfg.material.active].planeData

    # make image_series
    image_series = cfg.image_series.omegaseries

    # need instrument cfg later on down...
    instr_cfg = get_instrument_parameters(cfg)
    detector_params = np.hstack([
        instr_cfg['detector']['transform']['tilt_angles'],
        instr_cfg['detector']['transform']['t_vec_d'],
        instr_cfg['oscillation_stage']['chi'],
        instr_cfg['oscillation_stage']['t_vec_s'],
    ])
    rdim = cfg.instrument.detector.pixels.size[
        0] * cfg.instrument.detector.pixels.rows
    cdim = cfg.instrument.detector.pixels.size[
        1] * cfg.instrument.detector.pixels.columns
    panel_dims = (
        (-0.5 * cdim, -0.5 * rdim),
        (0.5 * cdim, 0.5 * rdim),
    )
    # UGH! hard-coded distortion...
    if instr_cfg['detector']['distortion']['function_name'] == 'GE_41RT':
        distortion = (
            dFuncs.GE_41RT,
            instr_cfg['detector']['distortion']['parameters'],
        )
    else:
        distortion = None

    min_compl = cfg.find_orientations.clustering.completeness

    # start logger
    logger.info("beginning analysis '%s'", cfg.analysis_name)

    # load the eta_ome orientation maps
    eta_ome = load_eta_ome_maps(cfg, pd, image_series, hkls=hkls, clean=clean)

    ome_range = (np.min(eta_ome.omeEdges), np.max(eta_ome.omeEdges))
    try:
        # are we searching the full grid of orientation space?
        qgrid_f = cfg.find_orientations.use_quaternion_grid
        quats = np.load(qgrid_f)
        logger.info("Using %s for full quaternion search", qgrid_f)
        hkl_ids = None
    except (IOError, ValueError, AttributeError):
        # or doing a seeded search?
        logger.info("Defaulting to seeded search")
        hkl_seeds = cfg.find_orientations.seed_search.hkl_seeds
        hkl_ids = [
            eta_ome.planeData.hklDataList[i]['hklID'] for i in hkl_seeds
        ]
        hklseedstr = ', '.join(
            [str(i) for i in eta_ome.planeData.hkls.T[hkl_seeds]])
        logger.info("Seeding search using hkls from %s: %s",
                    cfg.find_orientations.orientation_maps.file, hklseedstr)
        quats = generate_orientation_fibers(
            eta_ome,
            detector_params[6],
            cfg.find_orientations.threshold,
            cfg.find_orientations.seed_search.hkl_seeds,
            cfg.find_orientations.seed_search.fiber_ndiv,
            ncpus=cfg.multiprocessing,
        )
        if save_as_ascii:
            np.savetxt(os.path.join(cfg.working_dir, 'trial_orientations.dat'),
                       quats.T,
                       fmt="%.18e",
                       delimiter="\t")
            pass
        pass  # close conditional on grid search

    # generate the completion maps
    logger.info("Running paintgrid on %d trial orientations", quats.shape[1])
    if profile:
        logger.info("Profiling mode active, forcing ncpus to 1")
        ncpus = 1
    else:
        ncpus = cfg.multiprocessing
        logger.info("%d of %d available processors requested", ncpus,
                    mp.cpu_count())
    compl = idx.paintGrid(
        quats,
        eta_ome,
        etaRange=np.radians(cfg.find_orientations.eta.range),
        omeTol=np.radians(cfg.find_orientations.omega.tolerance),
        etaTol=np.radians(cfg.find_orientations.eta.tolerance),
        omePeriod=np.radians(cfg.find_orientations.omega.period),
        threshold=cfg.find_orientations.threshold,
        doMultiProc=ncpus > 1,
        nCPUs=ncpus)

    if save_as_ascii:
        np.savetxt(os.path.join(cfg.working_dir, 'completeness.dat'), compl)
    else:
        np.save(
            os.path.join(cfg.working_dir,
                         'scored_orientations_%s.npy' % analysis_id),
            np.vstack([quats, compl]))

    ##########################################################
    ##   Simulate N random grains to get neighborhood size  ##
    ##########################################################
    if hkl_ids is not None:
        ngrains = 100
        rand_q = mutil.unitVector(np.random.randn(4, ngrains))
        rand_e = np.tile(2.*np.arccos(rand_q[0, :]), (3, 1)) \
          * mutil.unitVector(rand_q[1:, :])
        refl_per_grain = np.zeros(ngrains)
        num_seed_refls = np.zeros(ngrains)
        print('fo: hklids = ', hkl_ids)
        for i in range(ngrains):
            grain_params = np.hstack(
                [rand_e[:, i],
                 xf.zeroVec.flatten(),
                 xf.vInv_ref.flatten()])
            sim_results = simulateGVecs(
                pd,
                detector_params,
                grain_params,
                ome_range=(ome_range, ),
                ome_period=(ome_range[0], ome_range[0] + 2 * np.pi),
                eta_range=np.radians(cfg.find_orientations.eta.range),
                panel_dims=panel_dims,
                pixel_pitch=cfg.instrument.detector.pixels.size,
                distortion=distortion,
            )
            refl_per_grain[i] = len(sim_results[0])
            # lines below fix bug when sim_results[0] is empty
            if refl_per_grain[i] > 0:
                num_seed_refls[i] = np.sum(
                    [sum(sim_results[0] == hkl_id) for hkl_id in hkl_ids])
            else:
                num_seed_refls[i] = 0
        #min_samples = 2
        min_samples = max(int(np.floor(0.5 * min_compl * min(num_seed_refls))),
                          2)
        mean_rpg = int(np.round(np.average(refl_per_grain)))
    else:
        min_samples = 1
        mean_rpg = 1

    logger.info("mean number of reflections per grain is %d", mean_rpg)
    logger.info("neighborhood size estimate is %d points", min_samples)

    # cluster analysis to identify orientation blobs, the final output:
    qbar, cl = run_cluster(compl,
                           quats,
                           pd.getQSym(),
                           cfg,
                           min_samples=min_samples)

    analysis_id = '%s_%s' % (
        cfg.analysis_name.strip().replace(' ', '-'),
        cfg.material.active.strip().replace(' ', '-'),
    )

    np.savetxt(os.path.join(cfg.working_dir,
                            'accepted_orientations_%s.dat' % analysis_id),
               qbar.T,
               fmt="%.18e",
               delimiter="\t")

    return
Exemplo n.º 44
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
Exemplo n.º 45
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
Exemplo n.º 46
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
Exemplo n.º 47
0
def angleAxisOfRotMat(R):
    """
    """
    if not isinstance(R, ndarray):
        raise RuntimeError, 'Input must be a 2 or 3-d ndarray'
    else:
        rdim = R.ndim
        if rdim == 2:
            nrot = 1
            R = tile(R, (1, 1, 1))
        elif rdim == 3:
            nrot = R.shape[0]
        else:
            raise RuntimeError, \
                  "R array must be (3, 3) or (n, 3, 3); input has dimension %d" \
                  % (rdim)

    #
    #  Find angle of rotation.
    #
    ca = 0.5 * (R[:, 0, 0] + R[:, 1, 1] + R[:, 2, 2] - 1)

    angle = arccosSafe(ca)

    #
    #  Three cases for the angle:
    #
    #  *   near zero -- matrix is effectively the identity
    #  *   near pi   -- binary rotation; need to find axis
    #  *   neither   -- general case; can use skew part
    #
    tol = 1.0e-4

    anear0 = angle < tol

    angle[anear0] = 0

    raxis = vstack([
        R[:, 2, 1] - R[:, 1, 2], R[:, 0, 2] - R[:, 2, 0],
        R[:, 1, 0] - R[:, 0, 1]
    ])
    raxis[:, anear0] = 1

    special = angle > pi - tol
    nspec = special.sum()
    if nspec > 0:
        tmp = R[special, :, :] + tile(I3, (nspec, 1, 1))
        tmpr = tmp.transpose(0, 2, 1).reshape(nspec * 3, 3).T

        tmpnrm = (tmpr * tmpr).sum(0).reshape(3, nspec)
        mx = tmpnrm.max(0)

        # remap indices
        maxInd = (tmpnrm == mx).nonzero()
        maxInd = c_[maxInd[0], maxInd[1]]

        tmprColInd = sort(maxInd[:, 0] + maxInd[:, 1] * nspec)

        saxis = tmpr[:, tmprColInd]

        raxis[:, special] = saxis

    return angle, unitVector(raxis)
Exemplo n.º 48
0
import sys, os, time

import numpy as np

from hexrd import matrixutil as mutil

from hexrd.xrd import rotations as rot
from hexrd.xrd import transforms_CAPI as xfcapi

n_quats = 1000000
rq = mutil.unitVector(np.random.randn(4, n_quats))
quats = np.array(rq.T, dtype=float, order='C')

# phi = 2. * rot.arccosSafe(rq[0, :])
# n   = np.tile(1. / np.sin(0.5*phi), (3, 1)) * rq[1:, :]

start0 = time.clock()  # time this
rMats0 = rot.rotMatOfQuat(rq)
elapsed0 = (time.clock() - start0)

# rMats1 = np.zeros((n_quats, 3, 3))
# for i in range(n_quats):
#     rMats1[i, :, :] = xfcapi.makeRotMatOfQuat(quats[i, :])

start1 = time.time()  # time this
rMats1 = xfcapi.makeRotMatOfQuat(quats)
elapsed1 = (time.time() - start1)
print "Time for %d quats:\t%g v. %g (%f)" % (
    n_quats, elapsed0 / float(n_quats), elapsed1 / float(n_quats),
    elapsed0 / elapsed1)
print "Maximum discrepancy:\t%f" % (np.amax(abs(rMats0 - rMats1)))
Exemplo n.º 49
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
Exemplo n.º 50
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
Exemplo n.º 51
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
Exemplo n.º 52
0
def objFuncSX(pFit, pFull, pFlag, dFunc, dFlag,
              xyo_det, hkls_idx, bMat, vInv,
              bVec, eVec, omePeriod,
              simOnly=False, return_value_flag=return_value_flag):
    """
    """
    npts = len(xyo_det)

    refineFlag = np.array(np.hstack([pFlag, dFlag]), dtype=bool)
    print refineFlag

    # pFull[refineFlag] = pFit/scl[refineFlag]
    pFull[refineFlag] = pFit

    if dFunc is not None:
        dParams = pFull[-len(dFlag):]
        xys = dFunc(xyo_det[:, :2], dParams)
    else:
        xys = xyo_det[:, :2]

    # detector quantities
    wavelength = pFull[0]

    rMat_d = xf.makeDetectorRotMat(pFull[1:4])
    tVec_d = pFull[4:7].reshape(3, 1)

    # sample quantities
    chi = pFull[7]
    tVec_s = pFull[8:11].reshape(3, 1)

    # crystal quantities
    rMat_c = xf.makeRotMatOfExpMap(pFull[11:14])
    tVec_c = pFull[14:17].reshape(3, 1)

    # stretch tensor comp matrix from MV notation in SAMPLE frame
    vMat_s = mutil.vecMVToSymm(vInv)

    # g-vectors:
    #   1. calculate full g-vector components in CRYSTAL frame from B
    #   2. rotate into SAMPLE frame and apply stretch
    #   3. rotate back into CRYSTAL frame and normalize to unit magnitude
    # IDEA: make a function for this sequence of operations with option for
    # choosing ouput frame (i.e. CRYSTAL vs SAMPLE vs LAB)
    gVec_c = np.dot(bMat, hkls_idx)
    gVec_s = np.dot(vMat_s, np.dot(rMat_c, gVec_c))
    gHat_c = mutil.unitVector(np.dot(rMat_c.T, gVec_s))

    match_omes, calc_omes = matchOmegas(
            xyo_det, hkls_idx, chi, rMat_c, bMat, wavelength,
            vInv=vInv, beamVec=bVec, etaVec=eVec, omePeriod=omePeriod)

    calc_xy = np.zeros((npts, 2))
    for i in range(npts):
        rMat_s = xfcapi.makeOscillRotMat([chi, calc_omes[i]])
        calc_xy[i, :] = xfcapi.gvecToDetectorXY(gHat_c[:, i],
                                                rMat_d, rMat_s, rMat_c,
                                                tVec_d, tVec_s, tVec_c,
                                                beamVec=bVec).flatten()
        pass
    if np.any(np.isnan(calc_xy)):
        raise RuntimeError(
            "infeasible pFull: may want to scale" +
            "back finite difference step size")

    # return values
    if simOnly:
        # return simulated values
        retval = np.hstack([calc_xy, calc_omes.reshape(npts, 1)])
    else:
        # return residual vector
        # IDEA: try angles instead of xys?
        diff_vecs_xy = calc_xy - xys[:, :2]
        diff_ome = xf.angularDifference(calc_omes, xyo_det[:, 2])
        retval = np.hstack([diff_vecs_xy,
                            diff_ome.reshape(npts, 1)
                            ]).flatten()
        if return_value_flag == 1:
            # return scalar sum of squared residuals
            retval = sum(abs(retval))
        elif return_value_flag == 2:
            # return DOF-normalized chisq
            # TODO: check this calculation
            denom = npts - len(pFit) - 1.
            if denom != 0:
                nu_fac = 1. / denom
            else:
                nu_fac = 1.
            nu_fac = 1 / (npts - len(pFit) - 1.)
            retval = nu_fac * sum(retval**2)
    return retval
Exemplo n.º 53
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
Exemplo n.º 54
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
def sxcal_obj_func(plist_fit,
                   plist_full,
                   param_flags,
                   dfuncs,
                   dparam_flags,
                   ndparams,
                   instr,
                   xyo_det,
                   hkls_idx,
                   bmat,
                   vinv_s,
                   ome_period,
                   bvec,
                   evec,
                   sim_only=False,
                   return_value_flag=None):
    """
    """
    # stack flags and force bool repr
    refine_flags = np.array(np.hstack([param_flags, dparam_flags]), dtype=bool)

    # fill out full parameter list
    # !!! no scaling for now
    plist_full[refine_flags] = plist_fit

    # instrument quantities
    wavelength = plist_full[0]
    chi = plist_full[1]
    tvec_s = plist_full[2:5]

    # calibration crystal quantities
    rmat_c = xfcapi.makeRotMatOfExpMap(plist_full[5:8])
    tvec_c = plist_full[8:11]

    # right now just stuck on the end and assumed
    # to all be the same length... FIX THIS
    dparams_all = plist_full[-len(dparam_flags):]
    xy_unwarped = {}
    meas_omes = {}
    calc_omes = {}
    calc_xy = {}
    ii = 11  # offset to start of panels...
    jj = 0
    npts_tot = 0
    for det_key, panel in instr.detectors.iteritems():
        xy_unwarped[det_key] = xyo_det[det_key][:, :2]
        npts_tot += len(xyo_det[det_key])
        dfunc = dfuncs[det_key]
        len_these_dps = ndparams[det_key]
        if dfunc is not None:  # do unwarping
            dparams = dparams_all[jj:jj + len_these_dps]
            jj += len_these_dps
            xy_unwarped[det_key] = dfunc(xy_unwarped[det_key], dparams)
            pass
        meas_omes[det_key] = xyo_det[det_key][:, 2]

        # get these panel params for convenience
        gparams = plist_full[ii:ii + 6]

        rmat_d = xfcapi.makeDetectorRotMat(gparams[:3])
        tvec_d = gparams[3:].reshape(3, 1)

        # transform G-vectors:
        # 1) convert inv. stretch tensor from MV notation in to 3x3
        # 2) take reciprocal lattice vectors from CRYSTAL to SAMPLE frame
        # 3) apply stretch tensor
        # 4) normalize reciprocal lattice vectors in SAMPLE frame
        # 5) transform unit reciprocal lattice vetors back to CRYSAL frame
        gvec_c = np.dot(bmat, hkls_idx[det_key].T)
        vmat_s = mutil.vecMVToSymm(vinv_s)
        ghat_s = mutil.unitVector(np.dot(vmat_s, np.dot(rmat_c, gvec_c)))
        ghat_c = np.dot(rmat_c.T, ghat_s)

        match_omes, calc_omes_tmp = fitting.matchOmegas(xyo_det[det_key],
                                                        hkls_idx[det_key].T,
                                                        chi,
                                                        rmat_c,
                                                        bmat,
                                                        wavelength,
                                                        vInv=vinv_s,
                                                        beamVec=bvec,
                                                        etaVec=evec,
                                                        omePeriod=ome_period)

        rmat_s_arr = xfcapi.makeOscillRotMatArray(
            chi, np.ascontiguousarray(calc_omes_tmp))
        calc_xy_tmp = xfcapi.gvecToDetectorXYArray(ghat_c.T, rmat_d,
                                                   rmat_s_arr, rmat_c, tvec_d,
                                                   tvec_s, tvec_c)
        if np.any(np.isnan(calc_xy_tmp)):
            print("infeasible parameters: " +
                  "may want to scale back finite difference step size")

        calc_omes[det_key] = calc_omes_tmp
        calc_xy[det_key] = calc_xy_tmp

        ii += 6
        pass

    # return values
    if sim_only:
        retval = {}
        for det_key in calc_xy.keys():
            # ??? calc_xy is always 2-d
            retval[det_key] = np.vstack(
                [calc_xy[det_key].T, calc_omes[det_key]]).T
    else:
        meas_xy_all = []
        calc_xy_all = []
        meas_omes_all = []
        calc_omes_all = []
        for det_key in xy_unwarped.keys():
            meas_xy_all.append(xy_unwarped[det_key])
            calc_xy_all.append(calc_xy[det_key])
            meas_omes_all.append(meas_omes[det_key])
            calc_omes_all.append(calc_omes[det_key])
            pass
        meas_xy_all = np.vstack(meas_xy_all)
        calc_xy_all = np.vstack(calc_xy_all)
        meas_omes_all = np.hstack(meas_omes_all)
        calc_omes_all = np.hstack(calc_omes_all)

        diff_vecs_xy = calc_xy_all - meas_xy_all
        diff_ome = xfcapi.angularDifference(calc_omes_all, meas_omes_all)
        retval = np.hstack([diff_vecs_xy,
                            diff_ome.reshape(npts_tot, 1)]).flatten()
        if return_value_flag == 1:
            retval = sum(abs(retval))
        elif return_value_flag == 2:
            denom = npts_tot - len(plist_fit) - 1.
            if denom != 0:
                nu_fac = 1. / denom
            else:
                nu_fac = 1.
            nu_fac = 1 / (npts_tot - len(plist_fit) - 1.)
            retval = nu_fac * sum(retval**2)
    return retval
Exemplo n.º 56
0
import sys, os, time

import numpy as np

from hexrd import matrixutil as mutil

from hexrd.xrd import rotations as rot
from hexrd.xrd import transforms_CAPI as xfcapi

n_quats = 1e6
rq = mutil.unitVector(np.random.randn(4, n_quats))
quats = np.array(rq.T, dtype=float, order='C')

""" NUMPY """
start0 = time.clock()                      # time this
rMats0 = rot.rotMatOfQuat(rq)
elapsed0 = (time.clock() - start0)

""" CAPI """
start1 = time.time()                      # time this
rMats1 = xfcapi.makeRotMatOfQuat(quats)
# rMats1 = np.zeros((n_quats, 3, 3))
# for i in range(n_quats):
#     rMats1[i, :, :] = xfcapi.makeRotMatOfQuat(quats[i, :])
elapsed1 = (time.time() - start1)
print "Time for %d quats:\t%g v. %g (%f)"%(n_quats, elapsed0/float(n_quats), elapsed1/float(n_quats), elapsed0/elapsed1)
print "Maximum discrepancy:\t%f" % (np.amax(abs(rMats0 - rMats1)))

""" NOTES

If I call xfcapi.makeRotMatOfQuat(quats) I get:
Exemplo n.º 57
0
def mockup_experiment():
    # user options
    # each grain is provided in the form of a quaternion.

    # The following array contains the quaternions for the array. Note that the
    # quaternions are in the columns, with the first row (row 0) being the real
    # part w. We assume that we are dealing with unit quaternions

    quats = np.array([[ 0.91836393,  0.90869942],
                      [ 0.33952917,  0.1834835 ],
                      [ 0.17216207,  0.10095837],
                      [ 0.10811041,  0.36111851]])

    n_grains = quats.shape[-1] # last dimension provides the number of grains
    phis = 2.*np.arccos(quats[0, :]) # phis are the angles for the quaternion
    ns = mutil.unitVector(quats[1:, :]) # ns contains the rotation axis as an unit vector
    exp_maps = np.array([phis[i]*ns[:, i] for i in range(n_grains)])
    rMat_c = rot.rotMatOfQuat(quats)

    cvec = np.arange(-25, 26)
    X, Y, Z = np.meshgrid(cvec, cvec, cvec)

    crd0 = 1e-3*np.vstack([X.flatten(), Y.flatten(), Z.flatten()]).T
    crd1 = crd0 + np.r_[0.100, 0.100, 0]
    crds = np.array([crd0, crd1])

    # make grain parameters
    grain_params = []
    for i in range(n_grains):
        for j in range(len(crd0)):
            grain_params.append(
                np.hstack([exp_maps[i, :], crds[i][j, :], xf.vInv_ref.flatten()])
            )

    # scan range and period
    ome_period = (0, 2*np.pi)
    ome_range = [ome_period,]
    ome_step = np.radians(1.)
    nframes = 0
    for i in range(len(ome_range)):
        del_ome = ome_range[i][1]-ome_range[i][0]
        nframes += int((ome_range[i][1]-ome_range[i][0])/ome_step)

    ome_edges = np.arange(nframes+1)*ome_step

    # instrument
    with open('./retiga.yml', 'r') as fildes:
        instr_cfg = yaml.load(fildes)

    tiltAngles = instr_cfg['detector']['transform']['tilt_angles']
    tVec_d = np.array(instr_cfg['detector']['transform']['t_vec_d']).reshape(3,1)
    chi = instr_cfg['oscillation_stage']['chi']
    tVec_s = np.array(instr_cfg['oscillation_stage']['t_vec_s']).reshape(3,1)
    rMat_d = xfcapi.makeDetectorRotMat(tiltAngles)
    rMat_s = xfcapi.makeOscillRotMat([chi, 0.])

    pixel_size = instr_cfg['detector']['pixels']['size']
    nrows = instr_cfg['detector']['pixels']['rows']
    ncols = instr_cfg['detector']['pixels']['columns']

    col_ps = pixel_size[1]
    row_ps = pixel_size[0]

    row_dim = row_ps*nrows # in mm
    col_dim = col_ps*ncols # in mm
    panel_dims = [(-0.5*ncols*col_ps, -0.5*nrows*row_ps),
                  ( 0.5*ncols*col_ps,  0.5*nrows*row_ps)]

    x_col_edges = col_ps * (np.arange(ncols + 1) - 0.5*ncols)
    y_row_edges = row_ps * (np.arange(nrows, -1, -1) - 0.5*nrows)
    #x_col_edges = np.arange(panel_dims[0][0], panel_dims[1][0] + 0.5*col_ps, col_ps)
    #y_row_edges = np.arange(panel_dims[0][1], panel_dims[1][1] + 0.5*row_ps, row_ps)
    rx, ry = np.meshgrid(x_col_edges, y_row_edges)

    gcrds = xfcapi.detectorXYToGvec(np.vstack([rx.flatten(), ry.flatten()]).T,
                                    rMat_d, rMat_s,
                                    tVec_d, tVec_s, np.zeros(3))

    max_pixel_tth = np.amax(gcrds[0][0])
    detector_params = np.hstack([tiltAngles, tVec_d.flatten(), chi,
                                 tVec_s.flatten()])
    distortion = None

    # a different parametrization for the sensor (makes for faster quantization)
    base = np.array([x_col_edges[0],
                     y_row_edges[0],
                     ome_edges[0]])
    deltas = np.array([x_col_edges[1] - x_col_edges[0],
                       y_row_edges[1] - y_row_edges[0],
                       ome_edges[1] - ome_edges[0]])
    inv_deltas = 1.0/deltas
    clip_vals = np.array([ncols, nrows])



    # dilation
    max_diameter = np.sqrt(3)*0.005
    row_dilation = np.ceil(0.5 * max_diameter/row_ps)
    col_dilation = np.ceil(0.5 * max_diameter/col_ps)

    # crystallography data
    from hexrd import valunits
    gold = material.Material('gold')
    gold.sgnum = 225
    gold.latticeParameters = [4.0782, ]
    gold.hklMax = 200
    gold.beamEnergy = valunits.valWUnit("wavelength", "ENERGY", 52, "keV")
    gold.planeData.exclusions = None
    gold.planeData.tThMax = max_pixel_tth #note this comes from info in the detector


    ns = argparse.Namespace()
    # grains related information
    ns.n_grains = n_grains # this can be derived from other values...
    ns.rMat_c = rMat_c # n_grains rotation matrices (one per grain)
    ns.exp_maps = exp_maps # n_grains exp_maps -angle * rotation axis- (one per grain)

    ns.plane_data = gold.planeData
    ns.detector_params = detector_params
    ns.pixel_size = pixel_size
    ns.ome_range = ome_range
    ns.ome_period = ome_period
    ns.x_col_edges = x_col_edges
    ns.y_row_edges = y_row_edges
    ns.ome_edges = ome_edges
    ns.ncols = ncols
    ns.nrows = nrows
    ns.nframes = nframes # used only in simulate...
    ns.rMat_d = rMat_d
    ns.tVec_d = tVec_d
    ns.chi = chi # note this is used to compute S... why is it needed?
    ns.tVec_s = tVec_s
    # ns.rMat_s = rMat_s
    # ns.tVec_s = tVec_s
    ns.rMat_c = rMat_c
    ns.row_dilation = row_dilation
    ns.col_dilation = col_dilation
    ns.distortion = distortion
    ns.panel_dims = panel_dims # used only in simulate...
    ns.base = base
    ns.inv_deltas = inv_deltas
    ns.clip_vals = clip_vals

    return grain_params, ns