Example #1
0
    def test_get_wavelength(self):
        wavelength = ks.get_wavelength(200000)
        self.assertEqual(np.round(wavelength * 1000, 3), 2.508)
        wavelength = ks.get_wavelength(60000)
        self.assertEqual(np.round(wavelength * 1000, 3), 4.866)

        with self.assertRaises(TypeError):
            ks.get_wavelength('lattice_parameter')
Example #2
0
 def test_ring_pattern_calculation(self):
     tags = ks.example(verbose=False)
     new_tags = ks.ring_pattern_calculation(tags)
     self.assertTrue('{2 6 4}' in new_tags)
     self.assertAlmostEqual(new_tags['{1 1 1}']['reciprocal_distance'],
                            3.369748652857738)
     self.assertAlmostEqual(new_tags['{1 1 1}']['real_distance'],
                            1 / 3.369748652857738)
     self.assertAlmostEqual(new_tags['{1 1 1}']['F'], 17.53103039316424)
     self.assertEqual(new_tags['{1 1 1}']['multiplicity'], 8)
Example #3
0
    def test_get_rotation_matrix(self):
        matrix, theta, phi = ks.get_rotation_matrix([1, 0, 0])
        self.assertEqual(theta, 90.)
        self.assertEqual(phi, 0.)

        matrix, theta, phi = ks.get_rotation_matrix([1, 1, 1])
        matrix_desired = [[0.40824829, -0.70710678, 0.57735027],
                          [0.40824829, 0.70710678, 0.57735027],
                          [-0.81649658, 0., 0.57735027]]
        np.testing.assert_allclose(matrix, matrix_desired)
Example #4
0
 def test_Zuo_fig_3_18(self):
     tags = ks.Zuo_fig_3_18(verbose=False)
     self.assertIsInstance(tags, dict)
     self.assertEqual(tags['crystal_name'], 'Silicon')
     self.assertEqual(tags['lattice_parameter_nm'], 0.514)
     self.assertEqual(tags['acceleration_voltage_V'], 101.6 * 1000.0)
     self.assertEqual(tags['convergence_angle_mrad'], 7.1)
     np.testing.assert_allclose(tags['zone_hkl'], np.array([-2, 2, 1]))
Example #5
0
    def test_ball_and_stick(self):
        in_tags = {
            'unit_cell': np.identity(3),
            'base': [[0, 0, 0], [0.5, 0.5, 0.5]],
            'elements': ['Fe', 'Fe']
        }
        corners, balls, atomic_number, bonds = ks.ball_and_stick(
            in_tags, extend=1, max_bond_length=1.)

        corners_desired = [[(0.0, 0.0), (0.0, 0.0), (0.0, 1.0)],
                           [(0.0, 0.0), (0.0, 1.0), (1.0, 1.0)],
                           [(0.0, 0.0), (1.0, 1.0), (1.0, 0.0)],
                           [(0.0, 0.0), (1.0, 0.0), (0.0, 0.0)],
                           [(0.0, 1.0), (0.0, 0.0), (0.0, 0.0)],
                           [(1.0, 1.0), (0.0, 0.0), (0.0, 1.0)],
                           [(1.0, 1.0), (0.0, 1.0), (1.0, 1.0)],
                           [(1.0, 1.0), (1.0, 1.0), (0.0, 1.0)],
                           [(1.0, 1.0), (1.0, 0.0), (0.0, 0.0)],
                           [(0.0, 1.0), (0.0, 0.0), (1.0, 1.0)],
                           [(0.0, 1.0), (1.0, 1.0), (0.0, 0.0)],
                           [(0.0, 1.0), (1.0, 1.0), (1.0, 1.0)]]
        np.testing.assert_allclose(corners, corners_desired)

        balls_desired = [[0., 0., 0.], [0., 0., 1.], [0., 1.,
                                                      0.], [0., 1., 1.],
                         [1., 0., 0.], [1., 0., 1.], [1., 1., 0.],
                         [1., 1., 1.], [0.5, 0.5, 0.5]]
        np.testing.assert_allclose(balls, balls_desired)

        self.assertTrue(len(atomic_number) == 9)

        bonds_desired = [[(0.0, 0.5), (0.0, 0.5), (0.0, 0.5)],
                         [(0.0, 0.5), (0.0, 0.5), (1.0, 0.5)],
                         [(0.0, 0.5), (1.0, 0.5), (0.0, 0.5)],
                         [(0.0, 0.5), (1.0, 0.5), (1.0, 0.5)],
                         [(1.0, 0.5), (0.0, 0.5), (0.0, 0.5)],
                         [(1.0, 0.5), (0.0, 0.5), (1.0, 0.5)],
                         [(1.0, 0.5), (1.0, 0.5), (0.0, 0.5)],
                         [(1.0, 0.5), (1.0, 0.5), (1.0, 0.5)],
                         [(0.5, 0.0), (0.5, 1.0), (0.5, 0.0)],
                         [(0.5, 0.0), (0.5, 1.0), (0.5, 1.0)],
                         [(0.5, 1.0), (0.5, 0.0), (0.5, 0.0)],
                         [(0.5, 1.0), (0.5, 0.0), (0.5, 1.0)],
                         [(0.5, 1.0), (0.5, 1.0), (0.5, 0.0)],
                         [(0.5, 0.0), (0.5, 0.0), (0.5, 1.0)],
                         [(0.5, 1.0), (0.5, 1.0), (0.5, 1.0)]]
Example #6
0
    def test_zone_mistilt(self):
        rotated_zone_axis = ks.zone_mistilt([1, 0, 0], [45, 0, 0])
        np.testing.assert_allclose(rotated_zone_axis, [1, 0, 0])

        rotated_zone_axis = ks.zone_mistilt([1, 0, 0], [0, 10, 0])
        np.testing.assert_allclose(rotated_zone_axis,
                                   [0.98480775, 0., 0.17364818])

        with self.assertRaises(TypeError):
            ks.zone_mistilt([1, 0, 0], [0, 0])

        with self.assertRaises(TypeError):
            ks.zone_mistilt([1j, 0, 0], [0, 0])
Example #7
0
 def test_get_symmetry(self):
     # Todo: better test
     self.assertTrue(
         ks.get_symmetry(np.identity(3), [[0, 0, 0], [0.5, 0.5, 0.5]],
                         ['Fe', 'Fe']))
Example #8
0
 def test_example(self):
     tags = ks.example(verbose=False)
     self.assertEqual(tags['plot HOLZ'], 1)
     self.assertEqual(tags['plot HOLZ'], 1)
Example #9
0
 def test_feq(self):
     self.assertAlmostEqual(ks.feq('Au', 3.6), 7.43164303450277)
     self.assertAlmostEqual(ks.feq('Si', 12.6), 0.5398190143297035)
Example #10
0
    def test_diffraction_pattern(self):
        tags = ks.example(verbose=False)

        ks.kinematic_scattering(tags)
Example #11
0
 def test_make_pretty_labels(self):
     labels = ks.make_pretty_labels(np.array([[1, 0, 0], [1, 1, -1]]))
     self.assertEqual(labels[0], '[$\\bar {1},0,0} $]')
     self.assertEqual(labels[1], '[$\\bar {1},1,\\bar {1} $]')
Example #12
0
def deficient_holz_line(exact_bragg=False,
                        shift=False,
                        laue_zone=1,
                        color='black'):
    """
    Ewald sphere construction to explain Laue Circle and deficient HOLZ lines

    Parameters:
    exact_bragg: boolean
        whether to tilt into exact Bragg condition or along zone axis
    shift: boolean
        whether to shift exact Bragg condition onto zone axis origin
    laue_zone: int
        first or second Laue zone only
    color: string
        color of wave vectors and Ewald sphere
    """

    k_0 = [0, 1 / ks.get_wavelength(600)]
    d = .5  # lattice parameter in nm

    if laue_zone == 0:
        s_g = 1 / d + 0.6
    else:
        s_g = 1

    g = np.linspace(-5, 6, 12) * 1 / d
    g_d = np.array([5. / d + laue_zone * 1 / d / 2, laue_zone * 1 / d])
    g_sg = g_d.copy()
    g_sg[1] = g_d[1] + s_g  # point on Ewald sphere

    # reciprocal lattice
    plt.scatter(g[:-1], [0] * 11, color='red')
    plt.scatter(g - 1 / d / 2, [1 / d] * 12, color='blue')

    shift_x = shift_y = 0.
    d_theta = d_theta1 = d_theta2 = 0

    if exact_bragg:

        d_theta1 = np.arctan((1 / d * laue_zone + s_g) / g_d[0])
        d_theta2 = np.arctan((1 / d * laue_zone) / g_d[0])
        d_theta = -(d_theta1 - d_theta2)
        s_g = 0
        s = np.sin(d_theta)
        c = np.cos(d_theta)
        k_0 = [-s * k_0[1], c * k_0[1]]
        if shift:
            shift_x = -k_0[0]
            shift_y = np.linalg.norm(k_0) - k_0[1]
        d_theta = np.degrees(d_theta)

    k_0[0] += shift_x
    k_0[1] += shift_y

    # Ewald Sphere
    ewald_sphere = patches.Circle((k_0[0], k_0[1]),
                                  radius=np.linalg.norm(k_0),
                                  clip_on=False,
                                  zorder=10,
                                  linewidth=1,
                                  edgecolor=color,
                                  fill=False)
    plt.gca().add_artist(ewald_sphere)

    plt.gca().arrow(g[-1] + 1 / d / 4,
                    1 / d / 2,
                    0,
                    1 / d / 2,
                    head_width=0.3,
                    head_length=0.4,
                    fc='k',
                    ec='k',
                    length_includes_head=True)
    plt.gca().arrow(g[-1] + 1 / d / 4,
                    1 / d / 2,
                    0,
                    -1 / d / 2,
                    head_width=0.3,
                    head_length=0.4,
                    fc='k',
                    ec='k',
                    length_includes_head=True)
    plt.gca().annotate("$|g_{HOLZ}|$",
                       xytext=(g[-1] + 1 / d / 3, 1 / d / 3),
                       xy=(g[-1] + 1 / d / 3, 1 / d / 3))

    # k_0
    plt.scatter(k_0[0], k_0[1])
    plt.gca().arrow(k_0[0],
                    k_0[1],
                    -k_0[0] + shift_x,
                    -k_0[1] + shift_y,
                    head_width=0.3,
                    head_length=0.4,
                    fc=color,
                    ec=color,
                    length_includes_head=True)
    plt.gca().annotate("K$_0$",
                       xytext=(k_0[0] / 2, k_0[1] / 3),
                       xy=(k_0[0] / 2, k_0[1] / 2))

    # K_d Bragg of HOLZ reflection
    plt.gca().arrow(k_0[0],
                    k_0[1],
                    -k_0[0] + g_d[0] + shift_x,
                    -k_0[1] + g_d[1] + s_g + shift_y,
                    head_width=0.3,
                    head_length=0.4,
                    fc=color,
                    ec=color,
                    length_includes_head=True)
    plt.gca().annotate("K$_d$",
                       xytext=(k_0[0] + (g_d[0] - k_0[0]) / 2, k_0[1] / 2),
                       xy=(6.5 / d / 2, k_0[1] / 2))

    # s_g excitation Error of HOLZ reflection
    if s_g > 0:
        plt.gca().arrow(g_d[0],
                        g_d[1],
                        0,
                        s_g,
                        head_width=0.3,
                        head_length=0.4,
                        fc='k',
                        ec='k',
                        length_includes_head=True)
        plt.gca().annotate("s$_g$",
                           xytext=(g_d[0] * 1.01, g_d[1] + s_g / 3),
                           xy=(g_d[0] * 1.01, g_d[1] + s_g / 3))

    # Bragg angle
    g_sg = g_d
    g_sg[1] = g_d[1] + s_g
    plt.plot([0 + shift_x, g_sg[0] + shift_x], [0 + shift_y, g_d[1] + shift_y],
             color=color,
             linewidth=1,
             alpha=0.5,
             linestyle='--')
    plt.plot([k_0[0], g_sg[0] / 2 + shift_x], [k_0[1], g_sg[1] / 2 + shift_y],
             color=color,
             linewidth=1,
             alpha=0.5,
             linestyle='--')
    # d_theta = np.degrees(np.arctan(k_0[0]/k_0[1]))
    bragg_angle = patches.Arc(
        (k_0[0], k_0[1]),
        width=k_0[1],
        height=k_0[1],
        theta1=-90 + d_theta,
        theta2=-90 + d_theta +
        np.degrees(np.arcsin(np.linalg.norm(g_sg / 2) / k_0[1])),
        fc=color,
        ec=color)

    plt.gca().annotate(r"$\theta $",
                       xytext=(k_0[0] / 1.3, k_0[1] / 1.5),
                       xy=(k_0[0] / 2 + g_d[0] / 4, k_0[1] / 2))
    plt.gca().add_patch(bragg_angle)

    # deviation/tilt angle
    if np.abs(d_theta) > 0:
        if shift:
            deviation_angle = patches.Arc((k_0[0], k_0[1]),
                                          width=k_0[1] * 1.5,
                                          height=k_0[1] * 1.5,
                                          theta1=-90 + d_theta,
                                          theta2=-90,
                                          fc=color,
                                          ec=color,
                                          linewidth=3)
            plt.gca().annotate(r"$d \theta $",
                               xytext=(k_0[0] - 1.3, k_0[1] / 3.7),
                               xy=(k_0[0] + g_d[0] / 4, k_0[1] / 2))
            plt.gca().arrow(shift_x,
                            -2,
                            0,
                            2,
                            head_width=0.5,
                            head_length=0.6,
                            fc=color,
                            ec='black',
                            length_includes_head=True,
                            linewidth=3)
            plt.gca().annotate("deficient line",
                               xytext=(shift_x * 2, -2),
                               xy=(shift_x, 0))
        else:
            deviation_angle = patches.Arc((0, 0),
                                          width=k_0[1],
                                          height=k_0[1],
                                          theta1=np.degrees(d_theta2),
                                          theta2=np.degrees(d_theta1),
                                          fc=color,
                                          ec=color,
                                          linewidth=3)
            plt.gca().annotate(r"$d \theta $",
                               xytext=(g_d[0] * .8, 1 / d / 3),
                               xy=(g_d[0], 1 / d))

        plt.gca().add_patch(deviation_angle)
    plt.gca().set_aspect('equal')
    plt.xlim(-14, 14)
    plt.ylim(-4, k_0[1] * 1.1)
Example #13
0
 def test_kinematic_scattering(self):
     tags = ks.example(verbose=False)
     ks.kinematic_scattering(tags)
     self.assertIsInstance(tags['HOLZ'], dict)
     self.assertAlmostEqual(tags['wave_length_nm'], 0.0036695, delta=1e-6)
Example #14
0
    def test_check_sanity(self):
        self.assertFalse(ks.check_sanity({}))

        tags = ks.example(verbose=False)
        self.assertTrue(ks.check_sanity(tags))
Example #15
0
    def test_plotCBED(self):
        tags = ks.example(verbose=False)

        ks.kinematic_scattering(tags)
Example #16
0
 def test_metric_tensor(self):
     # Todo: better testing
     np.testing.assert_allclose(ks.metric_tensor(np.identity(3)),
                                np.identity(3))
Example #17
0
    def test_circles(self):
        tags = ks.example(verbose=False)

        ks.kinematic_scattering(tags)
Example #18
0
def deficient_kikuchi_line(s_g=0., color_B='black'):
    k_len = 1 / ks.get_wavelength(200)
    d = .2  # lattice parameter in nm

    g = np.linspace(-2, 2, 5) * 1 / d
    g_d = np.array([1 / d, 0])

    # recirocal lattice
    plt.scatter(g, [0] * 5, color='blue')

    alpha = -np.arctan(s_g / g_d[0])
    theta = -np.arcsin(g_d[0] / 2 / k_len)

    k_0 = np.array(
        [-np.sin(theta - alpha) * k_len,
         np.cos(theta - alpha) * k_len])
    k_d = np.array(
        [-np.sin(-theta - alpha) * k_len,
         np.cos(-theta - alpha) * k_len])
    k_i = np.array([-np.sin(theta - alpha) * 3, np.cos(theta - alpha) * 3])
    k_i_t = np.array([-np.sin(-alpha) * 3, np.cos(-alpha) * 3])

    kk_e = np.array([-np.sin(-theta) * k_len, np.cos(-theta) * k_len])
    kk_d = np.array([-np.sin(theta) * k_len, np.cos(theta) * k_len])

    # Ewald Sphere
    ewald_sphere = patches.Circle((k_0[0], k_0[1]),
                                  radius=np.linalg.norm(k_0),
                                  clip_on=False,
                                  zorder=10,
                                  linewidth=1,
                                  edgecolor=color_B,
                                  fill=False)
    plt.gca().add_artist(ewald_sphere)

    # K_0
    plt.plot([k_0[0], k_0[0]], [k_0[1], k_0[1] + 4],
             color='gray',
             linestyle='-',
             alpha=0.3)

    plt.gca().arrow(k_0[0] + k_i[0],
                    k_0[1] + k_i[1],
                    -k_i[0],
                    -k_i[1],
                    head_width=0.3,
                    head_length=0.4,
                    fc=color_B,
                    ec=color_B,
                    length_includes_head=True)
    plt.plot([k_0[0] + k_i_t[0], k_0[0] - k_i_t[0]],
             [k_0[1] + k_i_t[1], k_0[1] - k_i_t[1]],
             color='black',
             linestyle='--',
             alpha=0.5)
    plt.scatter(k_0[0], k_0[1], color='black')
    plt.gca().arrow(k_0[0],
                    k_0[1],
                    -k_0[0],
                    -k_0[1],
                    head_width=0.3,
                    head_length=0.4,
                    fc=color_B,
                    ec=color_B,
                    length_includes_head=True)
    plt.gca().annotate("K$_0$", xytext=(-k_0[0] / 2, 0), xy=(k_0[0] / 2, 0))

    plt.gca().arrow(k_0[0],
                    k_0[1],
                    -k_d[0],
                    -k_d[1],
                    head_width=0.3,
                    head_length=0.4,
                    fc=color_B,
                    ec=color_B,
                    length_includes_head=True)

    # K_e exces line
    plt.gca().arrow(k_0[0],
                    k_0[1],
                    -kk_e[0],
                    -kk_e[1],
                    head_width=0.3,
                    head_length=0.4,
                    fc='red',
                    ec='red',
                    length_includes_head=True)
    plt.gca().annotate("excess",
                       xytext=(k_0[0] - kk_e[0], -1),
                       xy=(-kk_e[0] + k_0[0], 0))
    plt.plot([k_0[0] - kk_e[0], k_0[0] - kk_e[0]], [-1, 1], color='red')

    # k_d deficient line
    plt.gca().arrow(k_0[0],
                    k_0[1],
                    -kk_d[0],
                    -kk_d[1],
                    head_width=0.3,
                    head_length=0.4,
                    fc='blue',
                    ec='blue',
                    length_includes_head=True)
    plt.plot([k_0[0] - kk_d[0], k_0[0] - kk_d[0]], [-1, 1], color='blue')
    plt.gca().annotate("deficient",
                       xytext=(k_0[0] - kk_d[0], -1),
                       xy=(k_0[0] - kk_d[0], 0))

    # s_g excitation Error of HOLZ reflection
    plt.gca().arrow(g_d[0],
                    g_d[1],
                    0,
                    s_g,
                    head_width=0.3,
                    head_length=0.4,
                    fc='k',
                    ec='k',
                    length_includes_head=True)
    plt.gca().annotate("s$_g$",
                       xytext=(g_d[0] * 1.01, g_d[1] + s_g / 3),
                       xy=(g_d[0] * 1.01, g_d[1] + s_g / 3))

    theta = np.degrees(theta)
    alpha = np.degrees(alpha)

    bragg_angle = patches.Arc((k_0[0], k_0[1]),
                              width=5.5,
                              height=5.5,
                              theta1=90 + theta - alpha,
                              theta2=90 - alpha,
                              fc='black',
                              ec='black')
    if alpha > 0:
        deviation_angle = patches.Arc((k_0[0], k_0[1]),
                                      width=6,
                                      height=6,
                                      theta1=90 - alpha,
                                      theta2=90,
                                      fc='black',
                                      ec='red')
    else:
        deviation_angle = patches.Arc((k_0[0], k_0[1]),
                                      width=6,
                                      height=6,
                                      theta1=90,
                                      theta2=90 - alpha,
                                      fc='black',
                                      ec='red')

    plt.gca().annotate(r"$\theta$",
                       xytext=(k_0[0] + k_i_t[0] / 1.3, k_0[1] + 2),
                       xy=(k_0[0] + k_i_t[0], k_0[1] + 2))
    plt.gca().annotate(r"$\alpha$",
                       xytext=(k_0[0] + k_i_t[0] / 1.3, k_0[1] + 3),
                       xy=(k_0[0] + k_i_t[0], k_0[1] + 3),
                       color='red')
    plt.gca().add_patch(bragg_angle)
    plt.gca().add_patch(deviation_angle)

    plt.xlim(-12, 12)
    plt.ylim(-2, k_0[1] * 1.4)
    plt.gca().set_aspect('equal')
Example #19
0
 def test_vector_norm(self):
     g = [[2, 3, 4], [4, 5, 6]]
     vector_length = ks.vector_norm(g)
     np.testing.assert_allclose(vector_length, np.linalg.norm(g, axis=1))