예제 #1
0
 def calc_offset_for_hkl(self, hkl_offset, hkl_ref):
     """
     Calculate polar and azimuthal angles and scaling factor
     relating offset and reference hkl values
     """
     d_ref = self._state.crystal.get_hkl_plane_distance(hkl_ref)
     hklref_nphi = self._UB * matrix([[hkl_ref[0]], [hkl_ref[1]],
                                      [hkl_ref[2]]])
     d_offset = self._state.crystal.get_hkl_plane_distance(hkl_offset)
     hkloff_nphi = self._UB * matrix([[hkl_offset[0]], [hkl_offset[1]],
                                      [hkl_offset[2]]])
     sc = d_ref / d_offset
     par_ref_off = cross3(hklref_nphi, hkloff_nphi)
     if norm3(par_ref_off) < SMALL:
         return 0, float('nan'), sc
     y_axis = cross3(hklref_nphi, matrix('0; 1; 0'))
     if norm3(y_axis) < SMALL:
         y_axis = cross3(hklref_nphi, matrix('0; 0; 1'))
     x_axis = cross3(y_axis, hklref_nphi)
     x_coord = cos(angle_between_vectors(hkloff_nphi, x_axis))
     y_coord = cos(angle_between_vectors(hkloff_nphi, y_axis))
     pol = angle_between_vectors(hklref_nphi, hkloff_nphi)
     if abs(y_coord) < SMALL and abs(x_coord) < SMALL:
         # Set azimuthal rotation matrix to identity
         az = 0
     else:
         az = atan2(y_coord, x_coord)
     return pol, az, sc
예제 #2
0
    def repr_lines(self, ub_calculated, WIDTH=9, R=None):
        SET_LABEL = ' <- set'
        lines = []
        if self._n_phi_configured is not None:
            nphi_label = SET_LABEL
            nhkl_label = ''
        elif self._n_hkl_configured is not None:
            nphi_label = ''
            nhkl_label = SET_LABEL
        else:
            raise AssertionError(
                "Neither a manual n_phi nor n_hkl is configured")

        if ub_calculated:
            try:
                lines.append("   n_phi:".ljust(WIDTH) +
                             self._pretty_vector(R.I * self.n_phi) +
                             nphi_label)
            except AttributeError:
                lines.append("   n_phi:".ljust(WIDTH) +
                             self._pretty_vector(self.n_phi) + nphi_label)
            lines.append("   n_hkl:".ljust(WIDTH) +
                         self._pretty_vector(self.n_hkl) + nhkl_label)
            try:
                rotation_axis = R.I * cross3(matrix('0; 0; 1'), self.n_phi)
            except AttributeError:
                rotation_axis = cross3(matrix('0; 0; 1'), self.n_phi)
            if abs(norm(rotation_axis)) < SMALL:
                lines.append("   normal:".ljust(WIDTH) + "  None")
            else:
                rotation_axis = rotation_axis * (1 / norm(rotation_axis))
                cos_rotation_angle = dot3(matrix('0; 0; 1'), self.n_phi)
                rotation_angle = acos(cos_rotation_angle)
                lines.append("   normal:")
                lines.append("      angle:".ljust(WIDTH) + "% 9.5f" %
                             (rotation_angle * TODEG))
                lines.append("      axis:".ljust(WIDTH) +
                             self._pretty_vector(rotation_axis))

        else:  # no ub calculated
            if self._n_phi_configured is not None:
                try:
                    lines.append("   n_phi:".ljust(WIDTH) +
                                 self._pretty_vector(R.I *
                                                     self._n_phi_configured) +
                                 SET_LABEL)
                except AttributeError:
                    lines.append("   n_phi:".ljust(WIDTH) +
                                 self._pretty_vector(self._n_phi_configured) +
                                 SET_LABEL)
            elif self._n_hkl_configured is not None:
                lines.append("   n_hkl:".ljust(WIDTH) +
                             self._pretty_vector(self._n_hkl_configured) +
                             SET_LABEL)

        return lines
예제 #3
0
파일: calc.py 프로젝트: jamesmudd/diffcalc
def _calc_N(Q, n):
    """Return N as described by Equation 31"""
    Q = normalised(Q)
    n = normalised(n)
    if is_small(angle_between_vectors(Q, n)):
        raise ValueError('Q and n are parallel and cannot be used to create '
                         'an orthonormal matrix')
    Qxn = cross3(Q, n)
    QxnxQ = cross3(Qxn, Q)
    QxnxQ = normalised(QxnxQ)
    Qxn = normalised(Qxn)
    return matrix([[Q[0, 0], QxnxQ[0, 0], Qxn[0, 0]],
                   [Q[1, 0], QxnxQ[1, 0], Qxn[1, 0]],
                   [Q[2, 0], QxnxQ[2, 0], Qxn[2, 0]]])
예제 #4
0
def _calc_N(Q, n):
    """Return N as described by Equation 31"""
    Q = normalised(Q)
    n = normalised(n)
    if is_small(angle_between_vectors(Q, n)):
        raise ValueError('Q and n are parallel and cannot be used to create '
                         'an orthonormal matrix')
    Qxn = cross3(Q, n)
    QxnxQ = cross3(Qxn, Q)
    QxnxQ = normalised(QxnxQ)
    Qxn = normalised(Qxn)
    return matrix([[Q[0, 0], QxnxQ[0, 0], Qxn[0, 0]],
                   [Q[1, 0], QxnxQ[1, 0], Qxn[1, 0]],
                   [Q[2, 0], QxnxQ[2, 0], Qxn[2, 0]]])
예제 #5
0
    def __str__(self):
        lines = []
        if self._n_phi_configured is not None:
            lines.append("configured n_phi: " + self._pretty_vector(self._n_phi_configured))
        elif self._n_hkl_configured is not None:
            lines.append("configured n_hkl: " + self._pretty_vector(self._n_hkl_configured))
        else:
            raise AssertionError("Neither a manual n_phi nor n_hkl is configured")
        lines.append("           n_phi: " + self._pretty_vector(self.n_phi))
        lines.append("           n_hkl: " + self._pretty_vector(self.n_hkl))
        lines.append("")

        rotation_axis = cross3(matrix('0; 0; 1'), self.n_phi)
        if abs(norm(rotation_axis)) < SMALL:
            lines.append("no miscut")
        else:
            rotation_axis = rotation_axis * (1 / norm(rotation_axis))
            cos_rotation_angle = dot3(matrix('0; 0; 1'), self.n_phi)
            rotation_angle = acos(cos_rotation_angle)
            uvw = rotation_axis.T.tolist()[0]
            lines.append("miscut angle   : %.5f deg (phi axis to reference)" % (rotation_angle * TODEG))
            u_repr = (', '.join(['% .5f' % el for el in uvw]))
            lines.append("miscut direction: [%s] (in phi frame)" % u_repr)

        lines.append("")
        lines.append("To change: set n_hkl_configured or n_phi_configured property.")
        return '\n'.join(lines)
예제 #6
0
 def calc_hkl_offset(self, h, k, l, pol, az):
     """
     Calculate hkl orientation values that are related to
     the input hkl values by rotation with a given polar
     and azimuthal angles
     """
     hkl_nphi = self._UB * matrix([[h], [k], [l]])
     y_axis = cross3(hkl_nphi, matrix('0; 1; 0'))
     if norm3(y_axis) < SMALL:
         y_axis = cross3(hkl_nphi, matrix('0; 0; 1'))
     rot_polar = xyz_rotation(y_axis.T.tolist()[0], pol)
     rot_azimuthal = xyz_rotation(hkl_nphi.T.tolist()[0], az)
     hklrot_nphi = rot_azimuthal * rot_polar * hkl_nphi
     hklrot = self._UB.I * hklrot_nphi
     hkl_list = hklrot.T.tolist()[0]
     return hkl_list
예제 #7
0
    def repr_lines(self, ub_calculated, WIDTH=9):
        SET_LABEL = ' <- set'
        lines = []
        if self._n_phi_configured is not None:
            nphi_label = SET_LABEL
            nhkl_label = ''
        elif self._n_hkl_configured is not None:
            nphi_label = ''
            nhkl_label = SET_LABEL
        else:
            raise AssertionError("Neither a manual n_phi nor n_hkl is configured")
        
        if ub_calculated:
            lines.append("   n_phi:".ljust(WIDTH) + self._pretty_vector(self.n_phi) + nphi_label)
            lines.append("   n_hkl:".ljust(WIDTH) + self._pretty_vector(self.n_hkl) + nhkl_label)
            rotation_axis = cross3(matrix('0; 0; 1'), self.n_phi)
            if abs(norm(rotation_axis)) < SMALL:
                lines.append("   miscut:".ljust(WIDTH) + "  None")
            else:
                rotation_axis = rotation_axis * (1 / norm(rotation_axis))
                cos_rotation_angle = dot3(matrix('0; 0; 1'), self.n_phi)
                rotation_angle = acos(cos_rotation_angle)
                lines.append("   miscut:")
                lines.append("      angle:".ljust(WIDTH) + "% 9.5f" % (rotation_angle * TODEG))
                lines.append("      axis:".ljust(WIDTH) + self._pretty_vector(rotation_axis))
 
        else:  # no ub calculated
            if self._n_phi_configured is not None:
                lines.append("   n_phi:".ljust(WIDTH) + self._pretty_vector(self._n_phi_configured) + SET_LABEL)
            elif self._n_hkl_configured is not None:
                lines.append("   n_hkl:".ljust(WIDTH) + self._pretty_vector(self._n_hkl_configured) + SET_LABEL)

        return lines
예제 #8
0
    def _fit_ub_matrix_uncon(self, *args):
        if args is None:
            raise DiffcalcException(
                "Please specify list of reference reflection indices.")
        if len(args) < 3:
            raise DiffcalcException(
                "Need at least 3 reference reflections to fit UB matrix.")

        x = []
        y = []
        for idx in args:
            try:
                hkl_vals, pos, en, _, _ = self.get_reflection(idx)
            except IndexError:
                raise DiffcalcException(
                    "Cannot read reflection data for index %s" % str(idx))
            pos.changeToRadians()
            x.append(hkl_vals)
            wl = 12.3984 / en
            y_tmp = self._strategy.calculate_q_phi(pos) * 2. * pi / wl
            y.append(y_tmp.T.tolist()[0])

        xm = matrix(x)
        ym = matrix(y)
        b = (xm.T * xm).I * xm.T * ym

        b1, b2, b3 = matrix(b.tolist()[0]), matrix(b.tolist()[1]), matrix(
            b.tolist()[2])
        e1 = b1 / norm(b1)
        e2 = b2 - e1 * dot3(b2.T, e1.T)
        e2 = e2 / norm(e2)
        e3 = b3 - e1 * dot3(b3.T, e1.T) - e2 * dot3(b3.T, e2.T)
        e3 = e3 / norm(e3)

        new_umatrix = matrix(e1.tolist() + e2.tolist() + e3.tolist()).T

        V = dot3(cross3(b1.T, b2.T), b3.T)
        a1 = cross3(b2.T, b3.T) * 2 * pi / V
        a2 = cross3(b3.T, b1.T) * 2 * pi / V
        a3 = cross3(b1.T, b2.T) * 2 * pi / V
        ax, bx, cx = norm(a1), norm(a2), norm(a3)
        alpha = acos(dot3(a2, a3) / (bx * cx)) * TODEG
        beta = acos(dot3(a1, a3) / (ax * cx)) * TODEG
        gamma = acos(dot3(a1, a2) / (ax * bx)) * TODEG

        lattice_name = self._state.crystal.getLattice()[0]
        return new_umatrix, (lattice_name, ax, bx, cx, alpha, beta, gamma)
예제 #9
0
 def get_miscut_angle_axis(self, ubmatrix):
     y = self._get_surf_nphi()
     l = ubmatrix * y
     rotation_axis = self._tobj.transform(cross3(y, l), True)
     if abs(norm(rotation_axis)) < SMALL:
         rotation_axis = matrix('0; 0; 0')
         rotation_angle = 0
     else:
         rotation_axis = rotation_axis * (1 / norm(rotation_axis))
         cos_rotation_angle = bound(dot3(y, l) / norm(l))
         rotation_angle = acos(cos_rotation_angle) * TODEG
     return rotation_angle, rotation_axis
예제 #10
0
 def calc_miscut(self, h, k, l, pos):
     """
     Calculate miscut angle and axis that matches
     given hkl position and diffractometer angles
     """
     q_vec = self._strategy.calculate_q_phi(pos)
     hkl_nphi = self._UB * matrix([[h], [k], [l]])
     try:
         axis = cross3(self._ROT.I * q_vec, self._ROT.I * hkl_nphi)
     except AttributeError:
         axis = cross3(q_vec, hkl_nphi)
     norm_axis = norm(axis)
     if norm_axis < SMALL:
         return None, None
     axis = axis / norm(axis)
     try:
         miscut = acos(
             bound(dot3(q_vec, hkl_nphi) /
                   (norm(q_vec) * norm(hkl_nphi)))) * TODEG
     except AssertionError:
         return None, None
     return miscut, axis.T.tolist()[0]
예제 #11
0
    def str_lines_u_angle_and_axis(self):
        lines = []
        fmt = "% 9.5f % 9.5f % 9.5f"
        y = matrix('0; 0; 1')
        try:
            rotation_axis = cross3(self._ROT * y, self._ROT * self.U * y)
        except TypeError:
            rotation_axis = cross3(y, self.U * y)
        if abs(norm(rotation_axis)) < SMALL:
            lines.append("   miscut angle:".ljust(WIDTH) + "  0")
        else:
            rotation_axis = rotation_axis * (1 / norm(rotation_axis))
            cos_rotation_angle = dot3(y, self.U * y)
            rotation_angle = acos(cos_rotation_angle)

            lines.append("   miscut:")
            lines.append("      angle:".ljust(WIDTH) + "% 9.5f" %
                         (rotation_angle * TODEG))
            lines.append("       axis:".ljust(WIDTH) +
                         fmt % tuple((rotation_axis.T).tolist()[0]))

        return lines
예제 #12
0
    def _calc_UB(self, h1, h2, u1p, u2p):
        B = self._state.crystal.B
        h1c = B * h1
        h2c = B * h2

        # Create modified unit vectors t1, t2 and t3 in crystal and phi systems
        t1c = h1c
        t3c = cross3(h1c, h2c)
        t2c = cross3(t3c, t1c)

        t1p = u1p  # FIXED from h1c 9July08
        t3p = cross3(u1p, u2p)
        t2p = cross3(t3p, t1p)

        # ...and nornmalise and check that the reflections used are appropriate
        SMALL = 1e-4  # Taken from Vlieg's code
        e = DiffcalcException("Invalid orientation reflection(s)")

        def normalise(m):
            d = norm(m)
            if d < SMALL:
                raise e
            return m / d

        t1c = normalise(t1c)
        t2c = normalise(t2c)
        t3c = normalise(t3c)

        t1p = normalise(t1p)
        t2p = normalise(t2p)
        t3p = normalise(t3p)

        Tc = hstack([t1c, t2c, t3c])
        Tp = hstack([t1p, t2p, t3p])
        self._state.configure_calc_type(or0=1, or1=2)
        self._U = Tp * Tc.I
        self._UB = self._U * B
        self.save()
예제 #13
0
    def _calc_UB(self, h1, h2, u1p, u2p):
        B = self._state.crystal.B
        h1c = B * h1
        h2c = B * h2

        # Create modified unit vectors t1, t2 and t3 in crystal and phi systems
        t1c = h1c
        t3c = cross3(h1c, h2c)
        t2c = cross3(t3c, t1c)

        t1p = u1p  # FIXED from h1c 9July08
        t3p = cross3(u1p, u2p)
        t2p = cross3(t3p, t1p)

        # ...and nornmalise and check that the reflections used are appropriate
        SMALL = 1e-4  # Taken from Vlieg's code

        def normalise(m):
            d = norm(m)
            if d < SMALL:
                raise DiffcalcException(
                    "Invalid UB reference data. Please check that the specified "
                    "reference reflections/orientations are not parallel.")
            return m / d

        t1c = normalise(t1c)
        t2c = normalise(t2c)
        t3c = normalise(t3c)

        t1p = normalise(t1p)
        t2p = normalise(t2p)
        t3p = normalise(t3p)

        Tc = hstack([t1c, t2c, t3c])
        Tp = hstack([t1p, t2p, t3p])
        self._U = Tp * Tc.I
        self._UB = self._U * B
예제 #14
0
    def _findMatrixToTransformAIntoB(self, a, b):
        """
        Finds a particular matrix Mo that transforms the unit vector a into the
        unit vector b. Thats is it finds Mo Mo*a=b. a and b 3x1 matrixes and Mo
        is a 3x3 matrix.

        Throws an exception if this is not possible.
            """
        # Maths from the appendix of "Angle caluculations
        # for a 5-circle diffractometer used for surface X-ray diffraction",
        # E. Vlieg, J.F. van der Veen, J.E. Macdonald and M. Miller, J. of
        # Applied Cryst. 20 (1987) 330.
        #                                       - courtesy of Elias Vlieg again

        # equation A2: compute angle xi between vectors a and b
        cosxi = dot3(a, b)
        try:
            cosxi = bound(cosxi)
        except ValueError:
            raise Exception("Could not compute cos(xi), vectors a=%f and b=%f "
                            "must be of unit length" % (norm(a), norm(b)))
        xi = acos(cosxi)

        # Mo is identity matrix if xi zero (math below would blow up)
        if abs(xi) < 1e-10:
            return I

        # equation A3: c=cross(a,b)/sin(xi)
        c = cross3(a, b) * (1 / sin(xi))

        # equation A4: find D matrix that transforms a into the frame
        # x = a; y = c x a; z = c. */
        a1 = a[0, 0]
        a2 = a[1, 0]
        a3 = a[2, 0]
        c1 = c[0, 0]
        c2 = c[1, 0]
        c3 = c[2, 0]
        D = matrix([[a1, a2, a3],
                    [c2 * a3 - c3 * a2, c3 * a1 - c1 * a3, c1 * a2 - c2 * a1],
                    [c1, c2, c3]])

        # equation A5: create Xi to rotate by xi about z-axis
        XI = matrix([[cos(xi), -sin(xi), 0],
                     [sin(xi), cos(xi), 0],
                     [0, 0, 1]])

        # eq A6: compute Mo
        return D.I * XI * D
예제 #15
0
파일: calc.py 프로젝트: robwalton/diffcalc
    def str_lines_u_angle_and_axis(self):
        lines = []
        fmt = "% 9.5f % 9.5f % 9.5f"
        y = matrix('0; 0; 1')
        rotation_axis = cross3(y, self.U * y)
        if abs(norm(rotation_axis)) < SMALL:
            lines.append("   U angle:".ljust(WIDTH) + "  0")
        else:
            rotation_axis = rotation_axis * (1 / norm(rotation_axis))
            cos_rotation_angle = dot3(y, self.U * y)
            rotation_angle = acos(cos_rotation_angle)

            lines.append("      angle:".ljust(WIDTH) + "% 9.5f" % (rotation_angle * TODEG))
            lines.append("       axis:".ljust(WIDTH) + fmt % tuple((rotation_axis.T).tolist()[0]))
 
        return lines
예제 #16
0
파일: calc.py 프로젝트: jamesmudd/diffcalc
    def _findMatrixToTransformAIntoB(self, a, b):
        """
        Finds a particular matrix Mo that transforms the unit vector a into the
        unit vector b. Thats is it finds Mo Mo*a=b. a and b 3x1 matrixes and Mo
        is a 3x3 matrix.

        Throws an exception if this is not possible.
            """
        # Maths from the appendix of "Angle caluculations
        # for a 5-circle diffractometer used for surface X-ray diffraction",
        # E. Vlieg, J.F. van der Veen, J.E. Macdonald and M. Miller, J. of
        # Applied Cryst. 20 (1987) 330.
        #                                       - courtesy of Elias Vlieg again

        # equation A2: compute angle xi between vectors a and b
        cosxi = dot3(a, b)
        try:
            cosxi = bound(cosxi)
        except ValueError:
            raise Exception("Could not compute cos(xi), vectors a=%f and b=%f "
                            "must be of unit length" % (norm(a), norm(b)))
        xi = acos(cosxi)

        # Mo is identity matrix if xi zero (math below would blow up)
        if abs(xi) < 1e-10:
            return I

        # equation A3: c=cross(a,b)/sin(xi)
        c = cross3(a, b) * (1 / sin(xi))

        # equation A4: find D matrix that transforms a into the frame
        # x = a; y = c x a; z = c. */
        a1 = a[0, 0]
        a2 = a[1, 0]
        a3 = a[2, 0]
        c1 = c[0, 0]
        c2 = c[1, 0]
        c3 = c[2, 0]
        D = matrix([[a1, a2, a3],
                    [c2 * a3 - c3 * a2, c3 * a1 - c1 * a3, c1 * a2 - c2 * a1],
                    [c1, c2, c3]])

        # equation A5: create Xi to rotate by xi about z-axis
        XI = matrix([[cos(xi), -sin(xi), 0], [sin(xi), cos(xi), 0], [0, 0, 1]])

        # eq A6: compute Mo
        return D.I * XI * D
예제 #17
0
def __polar_to_hkl(params):
    from diffcalc.dc import dcyou as _dc
    from diffcalc.util import norm3, cross3
    import __main__

    sc, az = params
    h, k, l = __main__.hkl.getPosition()[:3]
    hkl_nphi = _dc._ub.ubcalc._UB * matrix([[h], [k], [l]])
    try:
        h_ref, k_ref, l_ref = _dc._ub.ubcalc.get_reflection(1)[0]
        ref_nphi = _dc._ub.ubcalc._UB * matrix([[h_ref], [k_ref], [l_ref]])
        ref_nphi *= norm3(hkl_nphi) / norm3(ref_nphi)
    except IndexError:
        raise DiffcalcException(
            "Please add one reference reflection into the reflection list.")
    nphi = _dc._ub.ubcalc.n_phi
    inplane_vec = cross3(ref_nphi, nphi)
    inplane_vec *= sqrt(1 - sc**2) * norm3(hkl_nphi) / norm3(inplane_vec)
    ref_nhkl = _dc._ub.ubcalc._UB.I * ref_nphi
    h_ref, k_ref, l_ref = ref_nhkl.T.tolist()[0]
    h_res, k_res, l_res = _dc._ub.ubcalc.calc_hkl_offset(
        h_ref, k_ref, l_ref, acos(sc), az)
    return h_res, k_res, l_res
예제 #18
0
    def calculate_UB_from_primary_only(self, idx=1):
        """
        Calculate orientation matrix with the shortest absolute angle change.
        Default: use first reflection.
        """

        # Algorithm from http://www.j3d.org/matrix_faq/matrfaq_latest.html

        # Get hkl and angle values for the first two reflections
        if self._state.reflist is None:
            raise DiffcalcException(
                "Cannot calculate a u matrix until a UBCalcaluation has been "
                "started with newub")
        try:
            (h, pos, _, _, _) = self.get_reflection(idx)
        except IndexError:
            raise DiffcalcException(
                "One reflection is required to calculate a u matrix")

        h = matrix([h]).T  # row->column
        pos.changeToRadians()
        B = self._state.crystal.B
        h_crystal = B * h
        h_crystal = h_crystal * (1 / norm(h_crystal))

        q_measured_phi = self._strategy.calculate_q_phi(pos)
        q_measured_phi = q_measured_phi * (1 / norm(q_measured_phi))

        rotation_axis = cross3(h_crystal, q_measured_phi)
        rotation_axis = rotation_axis * (1 / norm(rotation_axis))

        cos_rotation_angle = dot3(h_crystal, q_measured_phi)
        rotation_angle = acos(cos_rotation_angle)

        uvw = rotation_axis.T.tolist()[0]  # TODO: cleanup
        print "resulting U angle: %.5f deg" % (rotation_angle * TODEG)
        u_repr = (', '.join(['% .5f' % el for el in uvw]))
        print "resulting U axis direction: [%s]" % u_repr

        u, v, w = uvw
        rcos = cos(rotation_angle)
        rsin = sin(rotation_angle)
        m = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]  # TODO: tidy
        m[0][0] = rcos + u * u * (1 - rcos)
        m[1][0] = w * rsin + v * u * (1 - rcos)
        m[2][0] = -v * rsin + w * u * (1 - rcos)
        m[0][1] = -w * rsin + u * v * (1 - rcos)
        m[1][1] = rcos + v * v * (1 - rcos)
        m[2][1] = u * rsin + w * v * (1 - rcos)
        m[0][2] = v * rsin + u * w * (1 - rcos)
        m[1][2] = -u * rsin + v * w * (1 - rcos)
        m[2][2] = rcos + w * w * (1 - rcos)

        if self._UB is None:
            print "Calculating UB matrix from the first reflection only."
        else:
            print "Recalculating UB matrix from the first reflection only."
        print(
            "NOTE: A new UB matrix will not be automatically calculated "
            "when the orientation reflections are modified.")

        self._U = matrix(m)
        self._UB = self._U * B

        self._state.configure_calc_type(manual_U=self._U, or0=idx)
        self.save()
예제 #19
0
파일: calc.py 프로젝트: jamesmudd/diffcalc
    def calculate_UB(self):
        """
        Calculate orientation matrix. Uses first two orientation reflections
        as in Busang and Levy, but for the diffractometer in Lohmeier and
        Vlieg.
        """

        # Major variables:
        # h1, h2: user input reciprical 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 refelctions
        if self._state.reflist is None:
            raise DiffcalcException("Cannot calculate a U matrix until a "
                                    "UBCalculation has been started with "
                                    "'newub'")
        try:
            (h1, pos1, _, _, _) = self._state.reflist.getReflection(1)
            (h2, pos2, _, _, _) = self._state.reflist.getReflection(2)
        except IndexError:
            raise DiffcalcException(
                "Two reflections are required to calculate a u matrix")
        h1 = matrix([h1]).T  # row->column
        h2 = matrix([h2]).T
        pos1.changeToRadians()
        pos2.changeToRadians()

        # Compute the two reflections' reciprical lattice vectors in the
        # cartesian crystal frame
        B = self._state.crystal.B
        h1c = B * h1
        h2c = B * h2

        u1p = self._strategy.calculate_q_phi(pos1)
        u2p = self._strategy.calculate_q_phi(pos2)

        # Create modified unit vectors t1, t2 and t3 in crystal and phi systems
        t1c = h1c
        t3c = cross3(h1c, h2c)
        t2c = cross3(t3c, t1c)

        t1p = u1p  # FIXED from h1c 9July08
        t3p = cross3(u1p, u2p)
        t2p = cross3(t3p, t1p)

        # ...and nornmalise and check that the reflections used are appropriate
        SMALL = 1e-4  # Taken from Vlieg's code
        e = DiffcalcException("Invalid orientation reflection(s)")

        def normalise(m):
            d = norm(m)
            if d < SMALL:
                raise e
            return m / d

        t1c = normalise(t1c)
        t2c = normalise(t2c)
        t3c = normalise(t3c)

        t1p = normalise(t1p)
        t2p = normalise(t2p)
        t3p = normalise(t3p)

        Tc = hstack([t1c, t2c, t3c])
        Tp = hstack([t1p, t2p, t3p])
        self._state.configure_calc_type(or0=1, or1=2)
        self._U = Tp * Tc.I
        self._UB = self._U * B
        self.save()
예제 #20
0
파일: calc.py 프로젝트: robwalton/diffcalc
    def calculate_UB(self):
        """
        Calculate orientation matrix. Uses first two orientation reflections
        as in Busang and Levy, but for the diffractometer in Lohmeier and
        Vlieg.
        """

        # Major variables:
        # h1, h2: user input reciprical 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 refelctions
        if self._state.reflist is None:
            raise DiffcalcException(
                "Cannot calculate a U matrix until a " "UBCalculation has been started with " "'newub'"
            )
        try:
            (h1, pos1, _, _, _) = self._state.reflist.getReflection(1)
            (h2, pos2, _, _, _) = self._state.reflist.getReflection(2)
        except IndexError:
            raise DiffcalcException("Two reflections are required to calculate a u matrix")
        h1 = matrix([h1]).T  # row->column
        h2 = matrix([h2]).T
        pos1.changeToRadians()
        pos2.changeToRadians()

        # Compute the two reflections' reciprical lattice vectors in the
        # cartesian crystal frame
        B = self._state.crystal.B
        h1c = B * h1
        h2c = B * h2

        u1p = self._strategy.calculate_q_phi(pos1)
        u2p = self._strategy.calculate_q_phi(pos2)

        # Create modified unit vectors t1, t2 and t3 in crystal and phi systems
        t1c = h1c
        t3c = cross3(h1c, h2c)
        t2c = cross3(t3c, t1c)

        t1p = u1p  # FIXED from h1c 9July08
        t3p = cross3(u1p, u2p)
        t2p = cross3(t3p, t1p)

        # ...and nornmalise and check that the reflections used are appropriate
        SMALL = 1e-4  # Taken from Vlieg's code
        e = DiffcalcException("Invalid orientation reflection(s)")

        def normalise(m):
            d = norm(m)
            if d < SMALL:
                raise e
            return m / d

        t1c = normalise(t1c)
        t2c = normalise(t2c)
        t3c = normalise(t3c)

        t1p = normalise(t1p)
        t2p = normalise(t2p)
        t3p = normalise(t3p)

        Tc = hstack([t1c, t2c, t3c])
        Tp = hstack([t1p, t2p, t3p])
        self._state.configure_calc_type(or0=1, or1=2)
        self._U = Tp * Tc.I
        self._UB = self._U * B
        self.save()
예제 #21
0
파일: calc.py 프로젝트: robwalton/diffcalc
    def calculate_UB_from_primary_only(self):
        """
        Calculate orientation matrix with the shortest absolute angle change.
        Uses first orientation reflection
        """

        # Algorithm from http://www.j3d.org/matrix_faq/matrfaq_latest.html

        # Get hkl and angle values for the first two refelctions
        if self._state.reflist is None:
            raise DiffcalcException("Cannot calculate a u matrix until a UBCalcaluation has been " "started with newub")
        try:
            (h, pos, _, _, _) = self._state.reflist.getReflection(1)
        except IndexError:
            raise DiffcalcException("One reflection is required to calculate a u matrix")

        h = matrix([h]).T  # row->column
        pos.changeToRadians()
        B = self._state.crystal.B
        h_crystal = B * h
        h_crystal = h_crystal * (1 / norm(h_crystal))

        q_measured_phi = self._strategy.calculate_q_phi(pos)
        q_measured_phi = q_measured_phi * (1 / norm(q_measured_phi))

        rotation_axis = cross3(h_crystal, q_measured_phi)
        rotation_axis = rotation_axis * (1 / norm(rotation_axis))

        cos_rotation_angle = dot3(h_crystal, q_measured_phi)
        rotation_angle = acos(cos_rotation_angle)

        uvw = rotation_axis.T.tolist()[0]  # TODO: cleanup
        print "resulting U angle: %.5f deg" % (rotation_angle * TODEG)
        u_repr = ", ".join(["% .5f" % el for el in uvw])
        print "resulting U axis direction: [%s]" % u_repr

        u, v, w = uvw
        rcos = cos(rotation_angle)
        rsin = sin(rotation_angle)
        m = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]  # TODO: tidy
        m[0][0] = rcos + u * u * (1 - rcos)
        m[1][0] = w * rsin + v * u * (1 - rcos)
        m[2][0] = -v * rsin + w * u * (1 - rcos)
        m[0][1] = -w * rsin + u * v * (1 - rcos)
        m[1][1] = rcos + v * v * (1 - rcos)
        m[2][1] = u * rsin + w * v * (1 - rcos)
        m[0][2] = v * rsin + u * w * (1 - rcos)
        m[1][2] = -u * rsin + v * w * (1 - rcos)
        m[2][2] = rcos + w * w * (1 - rcos)

        if self._UB is None:
            print "Calculating UB matrix from the first reflection only."
        else:
            print "Recalculating UB matrix from the first reflection only."
        print (
            "NOTE: A new UB matrix will not be automatically calculated "
            "when the orientation reflections are modified."
        )

        self._state.configure_calc_type(or0=1)

        self._U = matrix(m)
        self._UB = self._U * B

        self.save()