Example #1
0
    def calculate_q_phi(self, pos):

        [MU, DELTA, NU, ETA, CHI, PHI] = create_you_matrices(*pos.totuple())
        # Equation 12: Compute the momentum transfer vector in the lab  frame
        q_lab = (NU * DELTA - I) * y
        # Transform this into the phi frame.
        return PHI.I * CHI.I * ETA.I * MU.I * q_lab
Example #2
0
    def calculate_q_phi(self, pos):

        [MU, DELTA, NU, ETA, CHI, PHI] = create_you_matrices(*pos.totuple())
        # Equation 12: Compute the momentum transfer vector in the lab  frame
        q_lab = (NU * DELTA - I) * y
        # Transform this into the phi frame.
        return PHI.I * CHI.I * ETA.I * MU.I * q_lab
Example #3
0
def youAnglesToHkl(pos, wavelength, UBmatrix):
    """Calculate miller indices from position in radians.
    """

    [MU, DELTA, NU, ETA, CHI, PHI] = create_you_matrices(*pos.totuple())

    q_lab = (NU * DELTA - I) * matrix([[0], [2 * pi / wavelength], [0]])   # 12

    hkl = UBmatrix.I * PHI.I * CHI.I * ETA.I * MU.I * q_lab

    return hkl[0, 0], hkl[1, 0], hkl[2, 0]
Example #4
0
def youAnglesToHkl(pos, wavelength, UBmatrix):
    """Calculate miller indices from position in radians.
    """

    [MU, DELTA, NU, ETA, CHI, PHI] = create_you_matrices(*pos.totuple())

    q_lab = (NU * DELTA - I) * matrix([[0], [2 * pi / wavelength], [0]])   # 12

    hkl = UBmatrix.I * PHI.I * CHI.I * ETA.I * MU.I * q_lab

    return hkl[0, 0], hkl[1, 0], hkl[2, 0]
Example #5
0
def _mu_and_qaz_from_eta_chi_phi(eta, chi, phi, theta, h_phi):
    
    h_phi_norm = normalised(h_phi)                                    # (68,69) 
    h1, h2, h3 = h_phi_norm[0, 0], h_phi_norm[1, 0], h_phi_norm[2, 0]
    a = sin(chi) * h2 * sin(phi) + sin(chi) * h1 * cos(phi) - cos(chi) * h3
    b = (- cos(chi) * sin(eta) * h2 * sin(phi)
         - cos(eta) * h1 * sin(phi) + cos(eta) * h2 * cos(phi)
         - cos(chi) * sin(eta) * h1 * cos(phi)
         - sin(chi) * sin(eta) * h3)
    c = -sin(theta)
    sin_bit = bound(c / sqrt(a * a + b * b))
    mu1 = asin(sin_bit) - atan2(b, a)
    mu2 = pi - asin(sin_bit) - atan2(b, a)

    mu1 = cut_at_minus_pi(mu1)
    mu2 = cut_at_minus_pi(mu2)
    
    # TODO: This special case should be *removed* when the gernal case has shown
    # toencompass it. It exists as fallback for a particular i16 experiment in
    # May 2013 --RobW.
#     if eta == chi == 0:
#         logger.debug("Testing against simplified equations for eta == chi == 0")
#         a = - h3
#         b = - h1 * sin(phi) + h2 * cos(phi)
#         sin_bit = bound(c / sqrt(a * a + b * b))
#         mu_simplified = pi - asin(sin_bit) - atan2(b, a)
#         mu_simplified = cut_at_minus_pi(mu_simplified)
#         if not ne(mu_simplified, mu):
#             raise AssertionError("mu_simplified != mu , %f!=%f" % (mu_simplified, mu))
        
    
    [MU, _, _, ETA, CHI, PHI] = create_you_matrices(mu1, None, None, eta, chi, phi)
    h_lab = MU * ETA * CHI * PHI * h_phi                                 # (11)
    qaz1 = atan2(h_lab[0, 0] , h_lab[2, 0])

    [MU, _, _, ETA, CHI, PHI] = create_you_matrices(mu2, None, None, eta, chi, phi)
    h_lab = MU * ETA * CHI * PHI * h_phi                                 # (11)
    qaz2 = atan2(h_lab[0, 0] , h_lab[2, 0])

    return (mu1, qaz1) , (mu2, qaz2)
Example #6
0
def _mu_and_qaz_from_eta_chi_phi(eta, chi, phi, theta, h_phi):
    
    h_phi_norm = normalised(h_phi)                                    # (68,69) 
    h1, h2, h3 = h_phi_norm[0, 0], h_phi_norm[1, 0], h_phi_norm[2, 0]
    a = sin(chi) * h2 * sin(phi) + sin(chi) * h1 * cos(phi) - cos(chi) * h3
    b = (- cos(chi) * sin(eta) * h2 * sin(phi)
         - cos(eta) * h1 * sin(phi) + cos(eta) * h2 * cos(phi)
         - cos(chi) * sin(eta) * h1 * cos(phi)
         - sin(chi) * sin(eta) * h3)
    c = -sin(theta)
    sin_bit = bound(c / sqrt(a * a + b * b))
    mu1 = asin(sin_bit) - atan2(b, a)
    mu2 = pi - asin(sin_bit) - atan2(b, a)

    mu1 = cut_at_minus_pi(mu1)
    mu2 = cut_at_minus_pi(mu2)
    
    # TODO: This special case should be *removed* when the gernal case has shown
    # toencompass it. It exists as fallback for a particular i16 experiment in
    # May 2013 --RobW.
#     if eta == chi == 0:
#         logger.debug("Testing against simplified equations for eta == chi == 0")
#         a = - h3
#         b = - h1 * sin(phi) + h2 * cos(phi)
#         sin_bit = bound(c / sqrt(a * a + b * b))
#         mu_simplified = pi - asin(sin_bit) - atan2(b, a)
#         mu_simplified = cut_at_minus_pi(mu_simplified)
#         if not ne(mu_simplified, mu):
#             raise AssertionError("mu_simplified != mu , %f!=%f" % (mu_simplified, mu))
        
    
    [MU, _, _, ETA, CHI, PHI] = create_you_matrices(mu1, None, None, eta, chi, phi)
    h_lab = MU * ETA * CHI * PHI * h_phi                                 # (11)
    qaz1 = atan2(h_lab[0, 0] , h_lab[2, 0])

    [MU, _, _, ETA, CHI, PHI] = create_you_matrices(mu2, None, None, eta, chi, phi)
    h_lab = MU * ETA * CHI * PHI * h_phi                                 # (11)
    qaz2 = atan2(h_lab[0, 0] , h_lab[2, 0])

    return (mu1, qaz1) , (mu2, qaz2)
Example #7
0
    def _anglesToVirtualAngles(self, pos, _wavelength):
        """Calculate pseudo-angles in radians from position in radians.

        Return theta, qaz, alpha, naz, tau, psi and beta in a dictionary.

        """

        # depends on surface normal n_lab.
        mu, delta, nu, eta, chi, phi = pos.totuple()

        theta, qaz = _theta_and_qaz_from_detector_angles(delta, nu)      # (19)

        [MU, _, _, ETA, CHI, PHI] = create_you_matrices(mu,
                                           delta, nu, eta, chi, phi)
        Z = MU * ETA * CHI * PHI
        n_lab = Z * self._get_n_phi()
        alpha = asin(bound((-n_lab[1, 0])))
        naz = atan2(n_lab[0, 0], n_lab[2, 0])                            # (20)

        cos_tau = cos(alpha) * cos(theta) * cos(naz - qaz) + \
                  sin(alpha) * sin(theta)
        tau = acos(bound(cos_tau))                                       # (23)

        # Compute Tau using the dot product directly (THIS ALSO WORKS)
#        q_lab = ( (NU * DELTA - I ) * matrix([[0],[1],[0]])
#        norm = norm(q_lab)
#        q_lab = matrix([[1],[0],[0]]) if norm == 0 else q_lab * (1/norm)
#        tau_from_dot_product = acos(bound(dot3(q_lab, n_lab)))

        sin_beta = 2 * sin(theta) * cos(tau) - sin(alpha)
        beta = asin(bound(sin_beta))                                     # (24)

        sin_tau = sin(tau)
        cos_theta = cos(theta)
        if sin_tau == 0:
            psi = float('Nan')
            print ('WARNING: Diffcalc could not calculate a unique azimuth '
                   '(psi) as the scattering vector (Q) and the reference '
                   'vector (n) are parallel')
        elif cos_theta == 0:
            psi = float('Nan')
            print ('WARNING: Diffcalc could not calculate a unique azimuth '
                   '(psi) because the scattering vector (Q) and xray beam are '
                   " are parallel and don't form a unique reference plane")
        else:
            cos_psi = ((cos(tau) * sin(theta) - sin(alpha)) /
                       (sin_tau * cos_theta))
            psi = acos(bound(cos_psi))                                   # (28)

        return {'theta': theta, 'qaz': qaz, 'alpha': alpha,
                'naz': naz, 'tau': tau, 'psi': psi, 'beta': beta}
Example #8
0
    def _anglesToVirtualAngles(self, pos, _wavelength):
        """Calculate pseudo-angles in radians from position in radians.

        Return theta, qaz, alpha, naz, tau, psi and beta in a dictionary.

        """

        # depends on surface normal n_lab.
        mu, delta, nu, eta, chi, phi = pos.totuple()

        theta, qaz = _theta_and_qaz_from_detector_angles(delta, nu)      # (19)

        [MU, _, _, ETA, CHI, PHI] = create_you_matrices(mu,
                                           delta, nu, eta, chi, phi)
        Z = MU * ETA * CHI * PHI
        n_lab = Z * self._get_n_phi()
        alpha = asin(bound((-n_lab[1, 0])))
        naz = atan2(n_lab[0, 0], n_lab[2, 0])                            # (20)

        cos_tau = cos(alpha) * cos(theta) * cos(naz - qaz) + \
                  sin(alpha) * sin(theta)
        tau = acos(bound(cos_tau))                                       # (23)

        # Compute Tau using the dot product directly (THIS ALSO WORKS)
#        q_lab = ( (NU * DELTA - I ) * matrix([[0],[1],[0]])
#        norm = norm(q_lab)
#        q_lab = matrix([[1],[0],[0]]) if norm == 0 else q_lab * (1/norm)
#        tau_from_dot_product = acos(bound(dot3(q_lab, n_lab)))

        sin_beta = 2 * sin(theta) * cos(tau) - sin(alpha)
        beta = asin(bound(sin_beta))                                     # (24)

        sin_tau = sin(tau)
        cos_theta = cos(theta)
        if sin_tau == 0:
            psi = float('Nan')
            print ('WARNING: Diffcalc could not calculate a unique azimuth '
                   '(psi) as the scattering vector (Q) and the reference '
                   'vector (n) are parallel')
        elif cos_theta == 0:
            psi = float('Nan')
            print ('WARNING: Diffcalc could not calculate a unique azimuth '
                   '(psi) because the scattering vector (Q) and xray beam are '
                   " are parallel and don't form a unique reference plane")
        else:
            cos_psi = ((cos(tau) * sin(theta) - sin(alpha)) /
                       (sin_tau * cos_theta))
            psi = acos(bound(cos_psi))                                   # (28)

        return {'theta': theta, 'qaz': qaz, 'alpha': alpha,
                'naz': naz, 'tau': tau, 'psi': psi, 'beta': beta}
Example #9
0
def _func_crystal(vals, uc_system, ref_data):
    trial_cr = CrystalUnderTest('trial', uc_system, 1, 1, 1, 90, 90, 90)
    try:
        trial_cr._set_cell_for_system(uc_system, *vals)
    except Exception:
        return 1e6

    res = 0
    I = matrix('1 0 0; 0 1 0; 0 0 1')
    for (hkl_vals, pos_vals, en) in ref_data:
        wl = 12.3984 / en
        [_, DELTA, NU, _, _, _] = create_you_matrices(*pos_vals.totuple())
        q_pos = (NU * DELTA - I) * matrix([[0], [2 * pi / wl], [0]])
        q_hkl = trial_cr.B * hkl_vals
        res += (norm(q_pos) - norm(q_hkl))**2
    return res
Example #10
0
def _func_orient(vals, crystal, ref_data):
    quat = _get_quat_from_u123(*vals)
    trial_u = _get_rot_matrix(*quat)
    tmp_ub = trial_u * crystal.B

    res = 0
    I = matrix('1 0 0; 0 1 0; 0 0 1')
    for (hkl_vals, pos_vals, en) in ref_data:
        wl = 12.3984 / en
        [MU, DELTA, NU, ETA, CHI,
         PHI] = create_you_matrices(*pos_vals.totuple())
        q_del = (NU * DELTA - I) * matrix([[0], [2 * pi / wl], [0]])
        q_vals = PHI.I * CHI.I * ETA.I * MU.I * q_del

        q_hkl = tmp_ub * hkl_vals
        res += angle_between_vectors(q_hkl, q_vals)
    return res
Example #11
0
    def calculate_UB(self, idx1=None, idx2=None):
        """Calculate UB matrix.
        
        Calculate UB matrix using two reference reflections and/or
        reference orientations.
        
        By default use the first two reference reflections when provided.
        If one or both reflections are not available use one or two reference
        orientations to complement mission reflection data.
        
        Parameters
        ----------
        idx1: int or str, optional
            The index or the tag of the first reflection or orientation.
        idx2: int or str, optional
            The index or the tag of the second reflection or orientation.
        """

        # Major variables:
        # h1, h2: user input reciprocal lattice vectors of the two reflections
        # h1c, h2c: user input vectors in cartesian crystal plane
        # pos1, pos2: measured diffractometer positions of the two reflections
        # u1a, u2a: measured reflection vectors in alpha frame
        # u1p, u2p: measured reflection vectors in phi frame

        # Get hkl and angle values for the first two reflections
        if self._state.reflist is None and self._state.orientlist is None:
            raise DiffcalcException("Cannot calculate a U matrix until a "
                                    "UBCalculation has been started with "
                                    "'newub'")
        if idx1 is not None and idx2 is None:
            self.calculate_UB_from_primary_only(idx1)
            return
        elif idx1 is None and idx2 is None:
            ref_data = []
            for func, idx in product(
                (self.get_reflection, self.get_orientation), (1, 2)):
                try:
                    ref_data.append(func(idx))
                except Exception:
                    pass
            try:
                ref1, ref2 = ref_data[:2]
            except ValueError:
                raise DiffcalcException(
                    "Cannot find calculate a U matrix. Please add "
                    "reference reflection and/or orientation data.")
        else:
            try:
                ref1 = self.get_reflection(idx1)
            except Exception:
                try:
                    ref1 = self.get_orientation(idx1)
                except Exception:
                    raise DiffcalcException(
                        "Cannot find first reflection or orientation with index %s"
                        % str(idx1))
            try:
                ref2 = self.get_reflection(idx2)
            except Exception:
                try:
                    ref2 = self.get_orientation(idx2)
                except Exception:
                    raise DiffcalcException(
                        "Cannot find second reflection or orientation with index %s"
                        % str(idx2))
        h1 = matrix([ref1[0]]).T  # row->column
        h2 = matrix([ref2[0]]).T

        # Compute the two reflections' reciprocal lattice vectors in the
        # cartesian crystal frame
        try:
            _, pos1, _ = ref1[:3]
            pos1.changeToRadians()
            u1p = self._strategy.calculate_q_phi(pos1)
        except AttributeError:
            _, r1, pos1 = ref1[:3]
            pos1.changeToRadians()
            [MU, _, _, ETA, CHI, PHI] = create_you_matrices(*pos1.totuple())
            Z = PHI.I * CHI.I * ETA.I * MU.I
            u1p = Z * matrix([r1]).T
        try:
            _, pos2, _ = ref2[:3]
            pos2.changeToRadians()
            u2p = self._strategy.calculate_q_phi(pos2)
        except AttributeError:
            _, r2, pos2 = ref2[:3]
            pos2.changeToRadians()
            [MU, _, _, ETA, CHI, PHI] = create_you_matrices(*pos2.totuple())
            Z = PHI.I * CHI.I * ETA.I * MU.I
            u2p = Z * matrix([r2]).T

        self._calc_UB(h1, h2, u1p, u2p)

        self._state.configure_calc_type(or0=idx1, or1=idx2)
        self.save()