Ejemplo n.º 1
0
    def _calc_omega(self):
        """
        calc omega, this is the angle between Q and the plane
        which is perpendicular to the axis of the chi circle.

        Notes:
        ------
        For nu=mu=0 this is the same as the four circle def:
        omega = 0.5*TTH - TH, where TTH is the detector motor (=del)
        and TH is the sample circle (=eta).  Therefore, for 
        mu=nu=0 and del=0.5*eta, omega = 0, which means that Q
        is in the plane perpendicular to the chi axis.

        Note check sign of results??? 
        """
        phi = self.angles['phi']
        chi = self.angles['chi']
        eta = self.angles['eta']
        mu = self.angles['mu']
        H = num.array([[cosd(eta), sind(eta), 0.],
                       [-sind(eta), cosd(eta), 0.], [0., 0., 1.]], float)
        M = num.array([[1., 0., 0.], [0., cosd(mu), -sind(mu)],
                       [0., sind(mu), cosd(mu)]], float)
        # check the mult order here!!!!
        # T = num.dot(H.transpose(),M.transpose())
        T = num.dot(M.transpose(), H.transpose())
        Qpp = num.dot(T, self.Q)
        #omega = -1.*cartesian_angle([Qpp[0], 0, Qpp[2]],Qpp)
        omega = cartesian_angle([Qpp[0], 0, Qpp[2]], Qpp)
        self.pangles['omega'] = omega
Ejemplo n.º 2
0
def calc_D(nu=0.0, delta=0.0):
    """
    Calculate the detector rotation matrix.
    Angles are in degrees

    Notes:
    ------
    D is the matrix that rotates a vector defined in the phi frame
    ie a vector defined with all angles zero => vphi.  After rotation
    the lab frame coordinates of the vector => vm are given by:
         vm = D*vphi
    For example 
                            |0|   
         kr_phi = (2pi/lam) |1|
                            |0|
    Since kr is defined by the detector rotation, the lab frame 
    coordinates of the kr vector after detector rotation are
         kr_m = D*kr_phi
    
    """
    D1 = num.array([[cosd(delta), sind(delta), 0.],
                    [-sind(delta), cosd(delta), 0.], [0., 0., 1.]])

    D2 = num.array([[1., 0., 0.], [0., cosd(nu), -sind(nu)],
                    [0., sind(nu), cosd(nu)]])

    D = num.dot(D2, D1)
    return (D)
Ejemplo n.º 3
0
def trans_point(p,theta=0.,scale=1.):
    """
    simple in-plane rotation of points
    """
    M = num.array([[cosd(theta), -sind(theta)],
                   [sind(theta),  cosd(theta)]])
    pp = scale*num.dot(M,p)
    return pp
Ejemplo n.º 4
0
def trans_point(p,theta=0.,scale=1.):
    """
    simple in-plane rotation of points
    """
    M = num.array([[cosd(theta), -sind(theta)],
                   [sind(theta),  cosd(theta)]])
    pp = scale*num.dot(M,p)
    return pp
Ejemplo n.º 5
0
def calc_kvecs(nu=0.0, delta=0.0, lam=1.0):
    """
    Calculate psic ki, kr in the cartesian lab frame.
    nu and delta are in degrees, lam is in angstroms
    """
    k = (2. * num.pi / lam)
    ki = k * num.array([0., 1., 0.], dtype=float)
    kr = k * num.array(
        [sind(delta),
         cosd(nu) * cosd(delta),
         sind(nu) * cosd(delta)],
        dtype=float)
    return (ki, kr)
Ejemplo n.º 6
0
    def calc_n(self, fchi=0.0, fphi=0.0):
        """
        Calculate the hkl values of a reference vector given
        the chi and phi settings that align this
        vector with the eta axis.

        Notes:
        ------
        This algorith is used, for example, 
        to compute the surface normal from the (flat) chi and
        (flat) phi angles that leave an optical reflection in
        a fixed position during an eta rotation 

        Note the vector is normalized such that
        the largest component is unity,
        ie n_hkl isn't a unit vector!
        
        """
        # polar angles
        sig_az = -fchi
        tau_az = -fphi

        # this block converts the chi and phi values to correctly
        # defined polar coordinates, ie 0<= sig_az <= 180deg .....
        if sig_az < 0.:
            sig_az = -1. * sig_az
            if tau_az < 0.:
                tau_az = 180. + tau_az
            elif tau_az > 0.:
                tau_az = tau_az - 180.

        # n in the unrotated lab frame (ie phi frame):
        # this is a unit vector!
        n_phi = num.array([
            sind(sig_az) * cosd(tau_az), -sind(sig_az) * sind(tau_az),
            cosd(sig_az)
        ])
        # n in HKL
        n_hkl = num.dot(num.linalg.inv(self.UB), n_phi)
        n_hkl = n_hkl / num.max(num.abs(n_hkl))

        # note if l-component is negative, then its
        # pointing into the surface (ie assume positive L
        # is the positive direction away from the surface)
        # careful here!!
        if n_hkl[2] < 0.:
            n_hkl = -1. * n_hkl

        # set n which triggers recalc of
        # all the psuedo angles
        self.set_n(n_hkl)
Ejemplo n.º 7
0
    def polarization(self, ):
        """
        Compute polarization correction factor.
        
        For a horizontally polarized beam (polarization vector
        parrallel to the lab-frame z direction) the polarization
        factor is normally defined as:
           p = 1-(cos(del)*sin(nu))^2
        For a beam with mixed horizontal and vertical polarization:
           p = fh( 1-(cos(del)*sin(nu))^2 ) + (1-fh)(1-sin(del)^2)
        where fh is the fraction of horizontal polarization.

        Measured data is corrected for polarization as: 
          Ic  = Im * cp = Im/p
        """
        fh = self.fh
        delta = self.gonio.angles['delta']
        nu = self.gonio.angles['nu']
        p = 1. - (cosd(delta) * sind(nu))**2.
        if fh != 1.0:
            p = fh * c_p + (1. - fh) * (1.0 - (sind(delta))**2.)
        if p == 0.:
            cp = 0.
        else:
            cp = 1. / p

        return cp
Ejemplo n.º 8
0
 def cartesian(self,shift=[0.,0.,0.]):
     """
     Calculates a cartesian basis using:
       Va = a' is parallel to a
       Vb = b' is perpendicular to a' and in the a/b plane
       Vc = c' is perpendicular to the a'/c' plane
     A shift vector may be specified to shift the origin
     of the cartesian lattice relative to the original lattice
     origin (specify shift in fractional coordinates of
     the original lattice)
     """
     (a,b,c,alp,bet,gam) = self.lattice.cell()
     (ar,br,cr,alpr,betr,gamr) = self.lattice.rcell()
     Va = [1./a,                 0. ,             0.]
     Vb = [-1./(a*tand(gam)), 1./(b*sind(gam)),   0.]
     Vc = [ar*cosd(betr),     br*cosd(alpr),      cr]
     self.basis(Va=Va,Vb=Vb,Vc=Vc,shift=shift)
Ejemplo n.º 9
0
 def cartesian(self,shift=[0.,0.,0.]):
     """
     Calculates a cartesian basis using:
       Va = a' is parallel to a
       Vb = b' is perpendicular to a' and in the a/b plane
       Vc = c' is perpendicular to the a'/c' plane
     A shift vector may be specified to shift the origin
     of the cartesian lattice relative to the original lattice
     origin (specify shift in fractional coordinates of
     the original lattice)
     """
     (a,b,c,alp,bet,gam) = self.lattice.cell()
     (ar,br,cr,alpr,betr,gamr) = self.lattice.rcell()
     Va = [1./a,                 0. ,             0.]
     Vb = [-1./(a*tand(gam)), 1./(b*sind(gam)),   0.]
     Vc = [ar*cosd(betr),     br*cosd(alpr),      cr]
     self.basis(Va=Va,Vb=Vb,Vc=Vc,shift=shift)
Ejemplo n.º 10
0
 def _calc_qaz(self):
     """
     Calc qaz, the angle btwn Q and the yz plane 
     """
     nu = self.angles['nu']
     delta = self.angles['delta']
     qaz = num.arctan2(sind(delta), cosd(delta) * sind(nu))
     qaz = num.degrees(qaz)
     self.pangles['qaz'] = qaz
Ejemplo n.º 11
0
    def _calc_tth(self):
        """
        Calculate 2Theta, the scattering angle

        Notes:
        ------
        This should be the same as:
          (ki,kr) = calc_kvecs(nu,delta,lambda)
           tth = cartesian_angle(ki,kr)

        You can also get this given h, the reciprocal lattice
        vector that is in the diffraction condition.  E.g.
          h   = self.calc_h()
          tth = self.lattice.tth(h)
        """
        nu = self.angles['nu']
        delta = self.angles['delta']
        tth = arccosd(cosd(delta) * cosd(nu))
        self.pangles['tth'] = tth
Ejemplo n.º 12
0
    def _calc_psi(self):
        """
        calc psi, this is the azmuthal angle of n wrt Q. 
        ie for tau != 0, psi is the rotation of n about Q

        Notes:
        ------
        Note this must be calc after tth, tau, and alpha!
        """
        tau = self.pangles['tau']
        tth = self.pangles['tth']
        alpha = self.pangles['alpha']
        #beta = self.calc_beta()
        #xx = (-cosd(tau)*sind(tth/2.) + sind(beta))
        xx = (cosd(tau) * sind(tth / 2.) - sind(alpha))
        denom = (sind(tau) * cosd(tth / 2.))
        if denom == 0:
            self.pangles['psi'] = 0.
            return
        xx = xx / denom
        psi = arccosd(xx)
        self.pangles['psi'] = psi
Ejemplo n.º 13
0
def calc_Z(phi=0.0, chi=0.0, eta=0.0, mu=0.0):
    """
    Calculate the psic goniometer rotation matrix Z
    for the 4 sample angles. Angles are in degrees

    Notes:
    ------
    Z is the matrix that rotates a vector defined in the phi frame
    ie a vector defined with all angles zero => vphi.  After rotation
    the lab frame coordinates of the vector => vm are given by:
         vm = Z*vphi
    """
    P = num.array([[cosd(phi), sind(phi), 0.], [-sind(phi),
                                                cosd(phi), 0.], [0., 0., 1.]],
                  float)
    X = num.array([[cosd(chi), 0., sind(chi)], [0., 1., 0.],
                   [-sind(chi), 0., cosd(chi)]], float)
    H = num.array([[cosd(eta), sind(eta), 0.], [-sind(eta),
                                                cosd(eta), 0.], [0., 0., 1.]],
                  float)
    M = num.array([[1., 0., 0.], [0., cosd(mu), -sind(mu)],
                   [0., sind(mu), cosd(mu)]], float)
    Z = num.dot(num.dot(num.dot(M, H), X), P)
    return Z
Ejemplo n.º 14
0
 def _calc_g(self):
     """
     Calculate the metric tensors and recip lattice params
     self.g  = real space metric tensor
     self.gr = recip space metric tensor
     """
     (a,b,c,alp,bet,gam) = self.cell()
     # real metric tensor
     self.g = num.array([ [ a*a, a*b*cosd(gam), a*c*cosd(bet) ],
                          [ b*a*cosd(gam), b*b, b*c*cosd(alp) ],
                          [ c*a*cosd(bet), c*b*cosd(alp), c*c ] ])
     # recip lattice metric tensor
     # and recip lattice params
     self.gr     = num.linalg.inv(self.g)
     self.ar     = num.sqrt(self.gr[0,0])
     self.br     = num.sqrt(self.gr[1,1])
     self.cr     = num.sqrt(self.gr[2,2])
     self.alphar = arccosd(self.gr[1,2]/(self.br*self.cr))
     self.betar  = arccosd(self.gr[0,2]/(self.ar*self.cr))
     self.gammar = arccosd(self.gr[0,1]/(self.ar*self.br))
Ejemplo n.º 15
0
 def _calc_g(self):
     """
     Calculate the metric tensors and recip lattice params
     self.g  = real space metric tensor
     self.gr = recip space metric tensor
     """
     (a,b,c,alp,bet,gam) = self.cell()
     # real metric tensor
     self.g = num.array([ [ a*a, a*b*cosd(gam), a*c*cosd(bet) ],
                          [ b*a*cosd(gam), b*b, b*c*cosd(alp) ],
                          [ c*a*cosd(bet), c*b*cosd(alp), c*c ] ])
     # recip lattice metric tensor
     # and recip lattice params
     self.gr     = num.linalg.inv(self.g)
     self.ar     = num.sqrt(self.gr[0,0])
     self.br     = num.sqrt(self.gr[1,1])
     self.cr     = num.sqrt(self.gr[2,2])
     self.alphar = arccosd(self.gr[1,2]/(self.br*self.cr))
     self.betar  = arccosd(self.gr[0,2]/(self.ar*self.cr))
     self.gammar = arccosd(self.gr[0,1]/(self.ar*self.br))
Ejemplo n.º 16
0
    def _calc_UB(self, ):
        """
        Calculate the orientation matrix, U,
        from the primary and secondary
        reflectons and given lattice

        Note dont really ever use B by itself.  so we
        should combine this and above to calc_UB and
        just store UB??
        """
        # use these, note they are used below on vectors
        # defined in the cartesian lab frame basis
        cross = num.cross
        norm = num.linalg.norm

        #Calculate the B matrix
        (a, b, c, alp, bet, gam) = self.lattice.cell()
        (ar, br, cr, alpr, betr, gamr) = self.lattice.rcell()
        B = num.array([[ar, br * cosd(gamr), cr * cosd(betr)],
                       [0., br * sind(gamr), -cr * sind(betr) * cosd(alp)],
                       [0., 0., 1. / c]])
        self.B = B

        # calc Z and Q for the OR reflections
        Z1 = calc_Z(self.or0['phi'], self.or0['chi'], self.or0['eta'],
                    self.or0['mu'])
        Q1 = calc_Q(self.or0['nu'], self.or0['delta'], self.or0['lam'])
        #
        Z2 = calc_Z(self.or1['phi'], self.or1['chi'], self.or1['eta'],
                    self.or1['mu'])
        Q2 = calc_Q(self.or1['nu'], self.or1['delta'], self.or1['lam'])

        # calc the phi frame coords for diffraction vectors
        # note divide out 2pi since the diffraction condition
        # is 2pi*h = Q
        vphi_1 = num.dot(num.linalg.inv(Z1), (Q1 / (2. * num.pi)))
        vphi_2 = num.dot(num.linalg.inv(Z2), (Q2 / (2. * num.pi)))

        #calc cartesian coords of h vectors
        hc_1 = num.dot(self.B, self.or0['h'])
        hc_2 = num.dot(self.B, self.or1['h'])

        #So at this point the following should be true:
        #     vphi_1 = U*hc_1
        #     vphi_2 = U*hc_2
        # and we could use these relations to solve for U.
        # But U solved directly from above is likely not to be orthogonal
        # since the angles btwn (vphi_1 and vphi_2) and (hc_1 and hc_2) are
        # not exactly the same due to expt errors.....
        # Therefore, get an orthogonal solution for U from the below treatment

        #define the following normalized vectors from hc vectors
        tc_1 = hc_1 / norm(hc_1)
        tc_3 = cross(tc_1, hc_2) / norm(cross(tc_1, hc_2))
        tc_2 = cross(tc_3, tc_1) / norm(cross(tc_3, tc_1))

        #define tphi vectors from vphi vectors
        tphi_1 = vphi_1 / norm(vphi_1)
        tphi_3 = cross(tphi_1, vphi_2) / norm(cross(tphi_1, vphi_2))
        tphi_2 = cross(tphi_3, tphi_1) / norm(cross(tphi_3, tphi_1))

        #define the following matrices
        Tc = num.transpose(num.array([tc_1, tc_2, tc_3]))
        Tphi = num.transpose(num.array([tphi_1, tphi_2, tphi_3]))

        # calc orientation matrix U
        # note either of the below work since Tc is orthogonal
        #self.U = num.dot(Tphi, Tc.transpose())
        self.U = num.dot(Tphi, num.linalg.inv(Tc))

        # calc UB
        self.UB = num.dot(self.U, self.B)

        #update h and psuedo angles...
        self.set_angles()
Ejemplo n.º 17
0
 def rotate(self, angle):
     x = self.x
     y = self.y
     self.x = x * cosd(angle) - y * sind(angle)
     self.y = x * sind(angle) + y * cosd(angle)
     return self