Example #1
0
    def _anglesToVirtualAngles(self, pos, wavelength):
        """
        Return dictionary of all virtual angles in radians from VliegPosition
        object win radians and wavelength in Angstroms. The virtual angles are:
        Bin, Bout, azimuth and 2theta.
        """

        # Create transformation matrices
        [ALPHA, DELTA, GAMMA, OMEGA, CHI, PHI] = createVliegMatrices(
            pos.alpha, pos.delta, pos.gamma, pos.omega, pos.chi, pos.phi)
        [SIGMA, TAU] = createVliegsSurfaceTransformationMatrices(
            self._getSigma() * TORAD, self._getTau() * TORAD)

        S = TAU * SIGMA
        y_vector = matrix([[0], [1], [0]])

        # Calculate Bin from equation 15:
        surfacenormal_alpha = OMEGA * CHI * PHI * S * matrix([[0], [0], [1]])
        incoming_alpha = ALPHA.I * y_vector
        minusSinBetaIn = dot3(surfacenormal_alpha, incoming_alpha)
        Bin = asin(bound(-minusSinBetaIn))

        # Calculate Bout from equation 16:
        #  surfacenormal_alpha has just ben calculated
        outgoing_alpha = DELTA * GAMMA * y_vector
        sinBetaOut = dot3(surfacenormal_alpha, outgoing_alpha)
        Bout = asin(bound(sinBetaOut))

        # Calculate 2theta from equation 25:

        cosTwoTheta = dot3(ALPHA * DELTA * GAMMA * y_vector, y_vector)
        twotheta = acos(bound(cosTwoTheta))
        psi = self._anglesToPsi(pos, wavelength)

        return {'Bin': Bin, 'Bout': Bout, 'azimuth': psi, '2theta': twotheta}
Example #2
0
 def checkSolution(omega, chi, phi):
     _, _, _, OMEGA, CHI, PHI = createVliegMatrices(
         None, None, None, omega, chi, phi)
     R = OMEGA * CHI * PHI
     RtimesH_phi = R * H_phi
     print ("R*H_phi=%s, Q_alpha=%s" %
            (R * H_phi.tolist(), Q_alpha.tolist()))
     return not differ(RtimesH_phi, Q_alpha, .0001)
Example #3
0
 def checkSolution(omega, chi, phi):
     _, _, _, OMEGA, CHI, PHI = createVliegMatrices(
         None, None, None, omega, chi, phi)
     R = OMEGA * CHI * PHI
     RtimesH_phi = R * H_phi
     print("R*H_phi=%s, Q_alpha=%s" %
           (R * H_phi.tolist(), Q_alpha.tolist()))
     return not differ(RtimesH_phi, Q_alpha, .0001)
Example #4
0
    def calculate_q_phi(self, pos):

        [ALPHA, DELTA, GAMMA, OMEGA, CHI, PHI] = createVliegMatrices(
           pos.alpha, pos.delta, pos.gamma, pos.omega, pos.chi, pos.phi)

        u1a = (DELTA * GAMMA - ALPHA.I) * y
        u1p = PHI.I * CHI.I * OMEGA.I * u1a
        return u1p
Example #5
0
    def _hklToAnglesZaxisModes(self, h, k, l, wavelength):
        """
        Return VliegPosition and virtual angles in radians from h, k & l and
        wavelength in Angstroms for z-axis modes. The virtual angles are those
        fixed or generated while calculating the position: Bin, Bout, and
        2theta.
        """
        # Section 6:

        # Results in radians during calculations, returned in degreess
        pos = VliegPosition(None, None, None, None, None, None)

        # Normalise hkl
        wavevector = 2 * pi / wavelength
        hkl = matrix([[h], [k], [l]])
        hklNorm = hkl * (1.0 / wavevector)

        # Compute hkl in phi axis coordinate frame
        hklPhi = self._getUBMatrix() * hkl
        hklPhiNorm = self._getUBMatrix() * hklNorm

        # Determine Chi and Phi (Equation 29):
        pos.phi = -self._getTau() * TORAD
        pos.chi = -self._getSigma() * TORAD

        # Equation 30:
        [ALPHA, DELTA, GAMMA, OMEGA, CHI,
         PHI] = createVliegMatrices(None, None, None, None, pos.chi, pos.phi)
        del ALPHA, DELTA, GAMMA, OMEGA
        Hw = CHI * PHI * hklPhi

        # Determine Bin and Bout:
        (Bin,
         Bout) = self._determineBinAndBoutInZaxisModes(Hw[2, 0] / wavevector)

        # Determine Alpha and Gamma (Equation 32):
        pos.alpha = Bin
        pos.gamma = Bout

        # Determine Delta:
        (pos.delta, twotheta) = self._determineDelta(hklPhiNorm, pos.alpha,
                                                     pos.gamma)

        # Determine Omega:
        delta = pos.delta
        gamma = pos.gamma
        d1 = (Hw[1, 0] * sin(delta) * cos(gamma) - Hw[0, 0] *
              (cos(delta) * cos(gamma) - cos(pos.alpha)))
        d2 = (Hw[0, 0] * sin(delta) * cos(gamma) + Hw[1, 0] *
              (cos(delta) * cos(gamma) - cos(pos.alpha)))

        if fabs(d2) < 1e-30:
            pos.omega = sign(d1) * sign(d2) * pi / 2.0
        else:
            pos.omega = atan2(d1, d2)

        # Gather up the virtual angles calculated along the way
        return pos, {'2theta': twotheta, 'Bin': Bin, 'Bout': Bout}
Example #6
0
    def _hklToAnglesZaxisModes(self, h, k, l, wavelength):
        """
        Return VliegPosition and virtual angles in radians from h, k & l and
        wavelength in Angstroms for z-axis modes. The virtual angles are those
        fixed or generated while calculating the position: Bin, Bout, and
        2theta.
        """
        # Section 6:

        # Results in radians during calculations, returned in degreess
        pos = VliegPosition(None, None, None, None, None, None)

        # Normalise hkl
        wavevector = 2 * pi / wavelength
        hkl = matrix([[h], [k], [l]])
        hklNorm = hkl * (1.0 / wavevector)

        # Compute hkl in phi axis coordinate frame
        hklPhi = self._getUBMatrix() * hkl
        hklPhiNorm = self._getUBMatrix() * hklNorm

        # Determine Chi and Phi (Equation 29):
        pos.phi = -self._getTau() * TORAD
        pos.chi = -self._getSigma() * TORAD

        # Equation 30:
        [ALPHA, DELTA, GAMMA, OMEGA, CHI, PHI] = createVliegMatrices(
                None, None, None, None, pos.chi, pos.phi)
        del ALPHA, DELTA, GAMMA, OMEGA
        Hw = CHI * PHI * hklPhi

        # Determine Bin and Bout:
        (Bin, Bout) = self._determineBinAndBoutInZaxisModes(
            Hw[2, 0] / wavevector)

        # Determine Alpha and Gamma (Equation 32):
        pos.alpha = Bin
        pos.gamma = Bout

        # Determine Delta:
        (pos.delta, twotheta) = self._determineDelta(hklPhiNorm, pos.alpha,
                                                     pos.gamma)

        # Determine Omega:
        delta = pos.delta
        gamma = pos.gamma
        d1 = (Hw[1, 0] * sin(delta) * cos(gamma) - Hw[0, 0] *
              (cos(delta) * cos(gamma) - cos(pos.alpha)))
        d2 = (Hw[0, 0] * sin(delta) * cos(gamma) + Hw[1, 0] *
              (cos(delta) * cos(gamma) - cos(pos.alpha)))

        if fabs(d2) < 1e-30:
            pos.omega = sign(d1) * sign(d2) * pi / 2.0
        else:
            pos.omega = atan2(d1, d2)

        # Gather up the virtual angles calculated along the way
        return pos, {'2theta': twotheta, 'Bin': Bin, 'Bout': Bout}
Example #7
0
    def calculate_q_phi(self, pos):

        [ALPHA, DELTA, GAMMA, OMEGA, CHI,
         PHI] = createVliegMatrices(pos.alpha, pos.delta, pos.gamma, pos.omega,
                                    pos.chi, pos.phi)

        u1a = (DELTA * GAMMA - ALPHA.I) * y
        u1p = PHI.I * CHI.I * OMEGA.I * u1a
        return u1p
Example #8
0
 def try__findOmegaAndChiToRotateHchiIntoQalpha(self, omega, chi):
     h_chi = matrix([[1], [1], [1]])
     h_chi = h_chi * (1 / norm(h_chi))
     [_, _, _, OMEGA, CHI, _] = createVliegMatrices(
         None, None, None, omega * TORAD, chi * TORAD, None)
     q_alpha = OMEGA * CHI * h_chi
     try:
         omega_calc, chi_calc = _findOmegaAndChiToRotateHchiIntoQalpha(
             h_chi, q_alpha)
     except ValueError, e:
         raise ValueError(str(e) + "\n, resulting from test where omega:%f"
                          " chi%f" % (self.omega, self.chi))
Example #9
0
 def try__findOmegaAndChiToRotateHchiIntoQalpha(self, omega, chi):
     h_chi = matrix([[1], [1], [1]])
     h_chi = h_chi * (1 / norm(h_chi))
     [_, _, _, OMEGA, CHI,
      _] = createVliegMatrices(None, None, None, omega * TORAD, chi * TORAD,
                               None)
     q_alpha = OMEGA * CHI * h_chi
     try:
         omega_calc, chi_calc = _findOmegaAndChiToRotateHchiIntoQalpha(
             h_chi, q_alpha)
     except ValueError, e:
         raise ValueError(
             str(e) + "\n, resulting from test where omega:%f"
             " chi%f" % (self.omega, self.chi))
Example #10
0
    def _anglesToPsi(self, pos, wavelength):
        """
        pos assumed in radians. -180<= psi <= 180
        """
        # Using Vlieg section 7.2

        # Needed througout:
        [ALPHA, DELTA, GAMMA, OMEGA, CHI,
         PHI] = createVliegMatrices(pos.alpha, pos.delta, pos.gamma, pos.omega,
                                    pos.chi, pos.phi)

        # Solve equation 49 for psi, the rotation of the a reference solution
        # about Qalpha or H_phi##

        # Find Ro, the reference solution to equation 46: R*H_phi=Q_alpha

        # Create Q_alpha from equation 47, (it comes normalised)
        Q_alpha = ((DELTA * GAMMA) - ALPHA.I) * matrix([[0], [1], [0]])
        Q_alpha = Q_alpha * (1 / norm(Q_alpha))

        # Finh H_phi
        h, k, l = self._anglesToHkl(pos, wavelength)
        H_phi = self._getUBMatrix() * matrix([[h], [k], [l]])
        normh = norm(H_phi)
        check(normh >= 1e-10, "reciprical lattice vector too close to zero")
        H_phi = H_phi * (1 / normh)

        # Find a solution Ro to Ro*H_phi=Q_alpha
        # This the reference solution with zero azimuth (psi)
        Ro = self._findMatrixToTransformAIntoB(H_phi, Q_alpha)

        # equation 48:
        R = OMEGA * CHI * PHI

        ## equation 50: Find a solution D to D*Q=norm(Q)*[[1],[0],[0]])
        D = self._findMatrixToTransformAIntoB(Q_alpha, matrix([[1], [0], [0]]))

        # solve equation 49 for psi
        # D*R = PSI*D*Ro
        # D*R*(D*Ro)^-1 = PSI
        PSI = D * R * ((D * Ro).I)

        # Find psi within PSI as defined in equation 51
        PSI_23 = PSI[1, 2]
        PSI_33 = PSI[2, 2]
        psi = atan2(PSI_23, PSI_33)

        #print "PSI: ", PSI.tolist()
        return psi
Example #11
0
    def _anglesToPsi(self, pos, wavelength):
        """
        pos assumed in radians. -180<= psi <= 180
        """
        # Using Vlieg section 7.2

        # Needed througout:
        [ALPHA, DELTA, GAMMA, OMEGA, CHI, PHI] = createVliegMatrices(
                pos.alpha, pos.delta, pos.gamma, pos.omega, pos.chi, pos.phi)

        # Solve equation 49 for psi, the rotation of the a reference solution
        # about Qalpha or H_phi##

        # Find Ro, the reference solution to equation 46: R*H_phi=Q_alpha

        # Create Q_alpha from equation 47, (it comes normalised)
        Q_alpha = ((DELTA * GAMMA) - ALPHA.I) * matrix([[0], [1], [0]])
        Q_alpha = Q_alpha * (1 / norm(Q_alpha))

        # Finh H_phi
        h, k, l = self._anglesToHkl(pos, wavelength)
        H_phi = self._getUBMatrix() * matrix([[h], [k], [l]])
        normh = norm(H_phi)
        check(normh >= 1e-10, "reciprical lattice vector too close to zero")
        H_phi = H_phi * (1 / normh)

        # Find a solution Ro to Ro*H_phi=Q_alpha
        # This the reference solution with zero azimuth (psi)
        Ro = self._findMatrixToTransformAIntoB(H_phi, Q_alpha)

        # equation 48:
        R = OMEGA * CHI * PHI

        ## equation 50: Find a solution D to D*Q=norm(Q)*[[1],[0],[0]])
        D = self._findMatrixToTransformAIntoB(Q_alpha, matrix([[1], [0], [0]]))

        # solve equation 49 for psi
        # D*R = PSI*D*Ro
        # D*R*(D*Ro)^-1 = PSI
        PSI = D * R * ((D * Ro).I)

        # Find psi within PSI as defined in equation 51
        PSI_23 = PSI[1, 2]
        PSI_33 = PSI[2, 2]
        psi = atan2(PSI_23, PSI_33)

        #print "PSI: ", PSI.tolist()
        return psi
Example #12
0
def vliegAnglesToHkl(pos, wavelength, UBMatrix):
    """
    Returns hkl indices from pos object in radians.
    """
    wavevector = 2 * pi / wavelength

    # Create transformation matrices
    [ALPHA, DELTA, GAMMA, OMEGA, CHI, PHI] = createVliegMatrices(
        pos.alpha, pos.delta, pos.gamma, pos.omega, pos.chi, pos.phi)

    # Create the plane normal vector in the alpha axis coordinate frame
    qa = ((DELTA * GAMMA) - ALPHA.I) * matrix([[0], [wavevector], [0]])

    # Transform the plane normal vector from the alpha frame to reciprical
    # lattice frame.
    hkl = UBMatrix.I * PHI.I * CHI.I * OMEGA.I * qa

    return hkl[0, 0], hkl[1, 0], hkl[2, 0]
Example #13
0
def vliegAnglesToHkl(pos, wavelength, UBMatrix):
    """
    Returns hkl indices from pos object in radians.
    """
    wavevector = 2 * pi / wavelength

    # Create transformation matrices
    [ALPHA, DELTA, GAMMA, OMEGA, CHI,
     PHI] = createVliegMatrices(pos.alpha, pos.delta, pos.gamma, pos.omega,
                                pos.chi, pos.phi)

    # Create the plane normal vector in the alpha axis coordinate frame
    qa = ((DELTA * GAMMA) - ALPHA.I) * matrix([[0], [wavevector], [0]])

    # Transform the plane normal vector from the alpha frame to reciprical
    # lattice frame.
    hkl = UBMatrix.I * PHI.I * CHI.I * OMEGA.I * qa

    return hkl[0, 0], hkl[1, 0], hkl[2, 0]
Example #14
0
    def _anglesToVirtualAngles(self, pos, wavelength):
        """
        Return dictionary of all virtual angles in radians from VliegPosition
        object win radians and wavelength in Angstroms. The virtual angles are:
        Bin, Bout, azimuth and 2theta.
        """

        # Create transformation matrices
        [ALPHA, DELTA, GAMMA, OMEGA, CHI,
         PHI] = createVliegMatrices(pos.alpha, pos.delta, pos.gamma, pos.omega,
                                    pos.chi, pos.phi)
        [SIGMA, TAU] = createVliegsSurfaceTransformationMatrices(
            self._getSigma() * TORAD,
            self._getTau() * TORAD)

        S = TAU * SIGMA
        y_vector = matrix([[0], [1], [0]])

        # Calculate Bin from equation 15:
        surfacenormal_alpha = OMEGA * CHI * PHI * S * matrix([[0], [0], [1]])
        incoming_alpha = ALPHA.I * y_vector
        minusSinBetaIn = dot3(surfacenormal_alpha, incoming_alpha)
        Bin = asin(bound(-minusSinBetaIn))

        # Calculate Bout from equation 16:
        #  surfacenormal_alpha has just ben calculated
        outgoing_alpha = DELTA * GAMMA * y_vector
        sinBetaOut = dot3(surfacenormal_alpha, outgoing_alpha)
        Bout = asin(bound(sinBetaOut))

        # Calculate 2theta from equation 25:

        cosTwoTheta = dot3(ALPHA * DELTA * GAMMA * y_vector, y_vector)
        twotheta = acos(bound(cosTwoTheta))
        psi = self._anglesToPsi(pos, wavelength)

        return {'Bin': Bin, 'Bout': Bout, 'azimuth': psi, '2theta': twotheta}
def armAnglesToLabVector(alpha, delta, gamma):
    [ALPHA, DELTA, GAMMA, _, _, _] = createVliegMatrices(
        alpha, delta, gamma, None, None, None)
    return ALPHA * DELTA * GAMMA * y_vector
Example #16
0
    def _determineSampleAnglesInFourAndFiveCircleModes(self, hklPhiNorm, alpha,
                                                       delta, gamma, Bin):
        """
        (omega, chi, phi, psi)=determineNonZAxisSampleAngles(hklPhiNorm, alpha,
        delta, gamma, sigma, tau) where hkl has been normalised by the
        wavevector and is in the phi Axis coordinate frame. All angles in
        radians. hklPhiNorm is a 3X1 matrix
        """

        def equation49through59(psi):
            # equation 49 R = (D^-1)*PI*D*Ro
            PSI = createVliegsPsiTransformationMatrix(psi)
            R = D.I * PSI * D * Ro

            #  eq 57: extract omega from R
            if abs(R[0, 2]) < 1e-20:
                omega = -sign(R[1, 2]) * sign(R[0, 2]) * pi / 2
            else:
                omega = -atan2(R[1, 2], R[0, 2])

            # eq 58: extract chi from R
            sinchi = sqrt(pow(R[0, 2], 2) + pow(R[1, 2], 2))
            sinchi = bound(sinchi)
            check(abs(sinchi) <= 1, 'could not compute chi')
            # (there are two roots to this equation, but only the first is also
            # a solution to R33=cos(chi))
            chi = asin(sinchi)

            # eq 59: extract phi from R
            if abs(R[2, 0]) < 1e-20:
                phi = sign(R[2, 1]) * sign(R[2, 1]) * pi / 2
            else:
                phi = atan2(-R[2, 1], -R[2, 0])
            return omega, chi, phi

        def checkSolution(omega, chi, phi):
            _, _, _, OMEGA, CHI, PHI = createVliegMatrices(
                None, None, None, omega, chi, phi)
            R = OMEGA * CHI * PHI
            RtimesH_phi = R * H_phi
            print ("R*H_phi=%s, Q_alpha=%s" %
                   (R * H_phi.tolist(), Q_alpha.tolist()))
            return not differ(RtimesH_phi, Q_alpha, .0001)

        # Using Vlieg section 7.2

        # Needed througout:
        [ALPHA, DELTA, GAMMA, _, _, _] = createVliegMatrices(
            alpha, delta, gamma, None, None, None)

        ## Find Ro, one possible solution to equation 46: R*H_phi=Q_alpha

        # Normalise hklPhiNorm (As it is currently normalised only to the
        # wavevector)
        normh = norm(hklPhiNorm)
        check(normh >= 1e-10, "reciprical lattice vector too close to zero")
        H_phi = hklPhiNorm * (1 / normh)

        # Create Q_alpha from equation 47, (it comes normalised)
        Q_alpha = ((DELTA * GAMMA) - ALPHA.I) * matrix([[0], [1], [0]])
        Q_alpha = Q_alpha * (1 / norm(Q_alpha))

        if self._getMode().name == '4cPhi':
            ### Use the fixed value of phi as the final constraint ###
            phi = self._getParameter('phi') * TORAD
            PHI = calcPHI(phi)
            H_chi = PHI * H_phi
            omega, chi = _findOmegaAndChiToRotateHchiIntoQalpha(H_chi, Q_alpha)
            return (omega, chi, phi, None)  # psi = None as not calculated
        else:
            ### Use Bin as the final constraint ###

            # Find a solution Ro to Ro*H_phi=Q_alpha
            Ro = self._findMatrixToTransformAIntoB(H_phi, Q_alpha)

            ## equation 50: Find a solution D to D*Q=norm(Q)*[[1],[0],[0]])
            D = self._findMatrixToTransformAIntoB(
                Q_alpha, matrix([[1], [0], [0]]))

            ## Find psi and create PSI

            # eq 54: compute u=D*Ro*S*[[0],[0],[1]], the surface normal in
            # psi frame
            [SIGMA, TAU] = createVliegsSurfaceTransformationMatrices(
                self._getSigma() * TORAD, self._getTau() * TORAD)
            S = TAU * SIGMA
            [u1], [u2], [u3] = (D * Ro * S * matrix([[0], [0], [1]])).tolist()
            # TODO: If u points along 100, then any psi is a solution. Choose 0
            if not differ([u1, u2, u3], [1, 0, 0], 1e-9):
                psi = 0
                omega, chi, phi = equation49through59(psi)
            else:
                # equation 53: V=A*(D^-1)
                V = ALPHA * D.I
                v21 = V[1, 0]
                v22 = V[1, 1]
                v23 = V[1, 2]
                # equation 55
                a = v22 * u2 + v23 * u3
                b = v22 * u3 - v23 * u2
                c = -sin(Bin) - v21 * u1  # TODO: changed sign from paper

                # equation 44
                # Try first root:
                def myatan2(y, x):
                    if abs(x) < 1e-20 and abs(y) < 1e-20:
                        return pi / 2
                    else:
                        return atan2(y, x)
                psi = 2 * myatan2(-(b - sqrt(b * b + a * a - c * c)), -(a + c))
                #psi = -acos(c/sqrt(a*a+b*b))+atan2(b,a)# -2*pi
                omega, chi, phi = equation49through59(psi)

            # if u points along z axis, the psi could have been either 0 or 180
            if (not differ([u1, u2, u3], [0, 0, 1], 1e-9) and
                abs(psi - pi) < 1e-10):
                # Choose 0 to match that read up by  angles-to-virtual-angles
                psi = 0.
            # if u points a long
            return (omega, chi, phi, psi)
def baseAnglesToLabVector(delta, gamma):
    [_, DELTA, GAMMA, _, _, _] = createVliegMatrices(
        None, delta, gamma, None, None, None)
    return GAMMA * DELTA * y_vector
def armAnglesToLabVector(alpha, delta, gamma):
    [ALPHA, DELTA, GAMMA, _, _,
     _] = createVliegMatrices(alpha, delta, gamma, None, None, None)
    return ALPHA * DELTA * GAMMA * y_vector
def baseAnglesToLabVector(delta, gamma):
    [_, DELTA, GAMMA, _, _, _] = createVliegMatrices(None, delta, gamma, None,
                                                     None, None)
    return GAMMA * DELTA * y_vector
Example #20
0
class TestVliegCoreMathBits(object):
    def setup_method(self):
        self.many = [
            -91, -90, -89, -46, -45, -44, -1, 0, 1, 44, 45, 46, 89, 90, 91
        ]
        self.many = (self.many + map(lambda x: x + 180, self.many) +
                     map(lambda x: x - 180, self.many))

    def test_check(self):
        check(True, 'Should not throw')
        with pytest.raises(Exception):
            check(False, 'string')
        with pytest.raises(DiffcalcException):
            check(False, DiffcalcException('dce'))

        def acallable(toPrint=None):
            if toPrint is None:
                print "Not throwing exception"
            else:
                print toPrint

        check(False, acallable)
        check(False, acallable, 'this should be printed')

    # TODO: Removed 2017-03-06, deprecated started code failing -- RobW.
    def SKIP__findOmegaAndChiToRotateHchiIntoQalpha_WithIntegerValues(self):
        for omega in self.many:
            for chi in self.many:
                print str(omega), ",", str(chi)
                self.try__findOmegaAndChiToRotateHchiIntoQalpha(omega, chi)

    def SKIP_findOmegaAndChiToRotateHchiIntoQalpha_WithRandomValues(self):
        for _ in range(10):
            for omega in self.many:
                for chi in self.many:
                    omega = omega + random.uniform(-.001, .001)
                    chi = chi + random.uniform(-.001, .001)
                    self.try__findOmegaAndChiToRotateHchiIntoQalpha(omega, chi)
                    #print str(omega), ",", str(chi)

    def test__findOmegaAndChiToRotateHchiIntoQalpha_WithTrickyOnes(self):
        tricky_ones = [(-45., -180.), (45., -180.), (135., -180.), (2000, 0.),
                       (225., 0.), (225., -180.), (-225., 0.), (-225., 0.),
                       (-225., -180.), (-135., -180.), (89.998894, -44.999218)]
        for omega, chi in tricky_ones:
            self.try__findOmegaAndChiToRotateHchiIntoQalpha(omega, chi)

    def try__findOmegaAndChiToRotateHchiIntoQalpha(self, omega, chi):
        h_chi = matrix([[1], [1], [1]])
        h_chi = h_chi * (1 / norm(h_chi))
        [_, _, _, OMEGA, CHI,
         _] = createVliegMatrices(None, None, None, omega * TORAD, chi * TORAD,
                                  None)
        q_alpha = OMEGA * CHI * h_chi
        try:
            omega_calc, chi_calc = _findOmegaAndChiToRotateHchiIntoQalpha(
                h_chi, q_alpha)
        except ValueError, e:
            raise ValueError(
                str(e) + "\n, resulting from test where omega:%f"
                " chi%f" % (self.omega, self.chi))
        [_, _, _, OMEGA, CHI,
         _] = createVliegMatrices(None, None, None, omega_calc, chi_calc, None)
        self.assertArraysNearlyEqual(OMEGA * CHI * h_chi, q_alpha, .000001,
                                     "omega: %f chi:%f" % (omega, chi))
Example #21
0
    def _determineSampleAnglesInFourAndFiveCircleModes(self, hklPhiNorm, alpha,
                                                       delta, gamma, Bin):
        """
        (omega, chi, phi, psi)=determineNonZAxisSampleAngles(hklPhiNorm, alpha,
        delta, gamma, sigma, tau) where hkl has been normalised by the
        wavevector and is in the phi Axis coordinate frame. All angles in
        radians. hklPhiNorm is a 3X1 matrix
        """
        def equation49through59(psi):
            # equation 49 R = (D^-1)*PI*D*Ro
            PSI = createVliegsPsiTransformationMatrix(psi)
            R = D.I * PSI * D * Ro

            #  eq 57: extract omega from R
            if abs(R[0, 2]) < 1e-20:
                omega = -sign(R[1, 2]) * sign(R[0, 2]) * pi / 2
            else:
                omega = -atan2(R[1, 2], R[0, 2])

            # eq 58: extract chi from R
            sinchi = sqrt(pow(R[0, 2], 2) + pow(R[1, 2], 2))
            sinchi = bound(sinchi)
            check(abs(sinchi) <= 1, 'could not compute chi')
            # (there are two roots to this equation, but only the first is also
            # a solution to R33=cos(chi))
            chi = asin(sinchi)

            # eq 59: extract phi from R
            if abs(R[2, 0]) < 1e-20:
                phi = sign(R[2, 1]) * sign(R[2, 1]) * pi / 2
            else:
                phi = atan2(-R[2, 1], -R[2, 0])
            return omega, chi, phi

        def checkSolution(omega, chi, phi):
            _, _, _, OMEGA, CHI, PHI = createVliegMatrices(
                None, None, None, omega, chi, phi)
            R = OMEGA * CHI * PHI
            RtimesH_phi = R * H_phi
            print("R*H_phi=%s, Q_alpha=%s" %
                  (R * H_phi.tolist(), Q_alpha.tolist()))
            return not differ(RtimesH_phi, Q_alpha, .0001)

        # Using Vlieg section 7.2

        # Needed througout:
        [ALPHA, DELTA, GAMMA, _, _,
         _] = createVliegMatrices(alpha, delta, gamma, None, None, None)

        ## Find Ro, one possible solution to equation 46: R*H_phi=Q_alpha

        # Normalise hklPhiNorm (As it is currently normalised only to the
        # wavevector)
        normh = norm(hklPhiNorm)
        check(normh >= 1e-10, "reciprical lattice vector too close to zero")
        H_phi = hklPhiNorm * (1 / normh)

        # Create Q_alpha from equation 47, (it comes normalised)
        Q_alpha = ((DELTA * GAMMA) - ALPHA.I) * matrix([[0], [1], [0]])
        Q_alpha = Q_alpha * (1 / norm(Q_alpha))

        if self._getMode().name == '4cPhi':
            ### Use the fixed value of phi as the final constraint ###
            phi = self._getParameter('phi') * TORAD
            PHI = calcPHI(phi)
            H_chi = PHI * H_phi
            omega, chi = _findOmegaAndChiToRotateHchiIntoQalpha(H_chi, Q_alpha)
            return (omega, chi, phi, None)  # psi = None as not calculated
        else:
            ### Use Bin as the final constraint ###

            # Find a solution Ro to Ro*H_phi=Q_alpha
            Ro = self._findMatrixToTransformAIntoB(H_phi, Q_alpha)

            ## equation 50: Find a solution D to D*Q=norm(Q)*[[1],[0],[0]])
            D = self._findMatrixToTransformAIntoB(Q_alpha,
                                                  matrix([[1], [0], [0]]))

            ## Find psi and create PSI

            # eq 54: compute u=D*Ro*S*[[0],[0],[1]], the surface normal in
            # psi frame
            [SIGMA, TAU] = createVliegsSurfaceTransformationMatrices(
                self._getSigma() * TORAD,
                self._getTau() * TORAD)
            S = TAU * SIGMA
            [u1], [u2], [u3] = (D * Ro * S * matrix([[0], [0], [1]])).tolist()
            # TODO: If u points along 100, then any psi is a solution. Choose 0
            if not differ([u1, u2, u3], [1, 0, 0], 1e-9):
                psi = 0
                omega, chi, phi = equation49through59(psi)
            else:
                # equation 53: V=A*(D^-1)
                V = ALPHA * D.I
                v21 = V[1, 0]
                v22 = V[1, 1]
                v23 = V[1, 2]
                # equation 55
                a = v22 * u2 + v23 * u3
                b = v22 * u3 - v23 * u2
                c = -sin(Bin) - v21 * u1  # TODO: changed sign from paper

                # equation 44
                # Try first root:
                def myatan2(y, x):
                    if abs(x) < 1e-20 and abs(y) < 1e-20:
                        return pi / 2
                    else:
                        return atan2(y, x)

                psi = 2 * myatan2(-(b - sqrt(b * b + a * a - c * c)), -(a + c))
                #psi = -acos(c/sqrt(a*a+b*b))+atan2(b,a)# -2*pi
                omega, chi, phi = equation49through59(psi)

            # if u points along z axis, the psi could have been either 0 or 180
            if (not differ([u1, u2, u3], [0, 0, 1], 1e-9)
                    and abs(psi - pi) < 1e-10):
                # Choose 0 to match that read up by  angles-to-virtual-angles
                psi = 0.
            # if u points a long
            return (omega, chi, phi, psi)