zone_axes.py ダウンロード/コピー
zone_axes.py
zone_axes.py
1"""
2概要: 立方晶系の結晶面とゾーン軸を3Dで可視化するスクリプト。
3詳細説明:
4 このスクリプトは、matplotlibを使用して3Dプロットを作成し、指定されたミラー指数(hkl)を持つ結晶面と、
5 それらの法線ベクトル、および特定のゾーン軸を描画します。
6 主に[001]ゾーン軸に属する結晶面を表示し、結晶学における面と軸の関係を視覚的に理解するのに役立ちます。
7 生成されたプロットはPNG画像として保存されます。
8関連リンク: :doc:`zone_axes_usage`
9"""
10import matplotlib.pyplot as plt
11import numpy as np
12from mpl_toolkits.mplot3d import Axes3D
13
14alpha = 0.1
15
16def plot_plane(ax, h, k, l, color, alpha, label):
17 """
18 概要: ミラー指数(hkl)で定義される結晶面を3D空間にプロットします。
19 詳細説明:
20 この関数は、立方晶系においてミラー指数(hkl)で定義される結晶面を、
21 平面方程式 hx + ky + lz = d (ここではd=1を仮定) に基づいて3Dプロットします。
22 プロット範囲はx, y, z軸それぞれ[-1.5, 1.5]に制限され、この範囲外に出る部分は表示されません。
23 ミラー指数に特定のゼロ値がある場合の特殊なケース(例: l=0, k=0, h=0)も処理します。
24 軸オブジェクトに直接描画を行い、明示的な戻り値はありません。
25 :param ax: matplotlibの3D軸オブジェクト。平面が描画されるAxes3Dインスタンス。
26 :type ax: mpl_toolkits.mplot3d.axes3d.Axes3D
27 :param h: 平面のミラー指数 h。
28 :type h: int
29 :param k: 平面のミラー指数 k。
30 :type k: int
31 :param l: 平面のミラー指数 l。
32 :type l: int
33 :param color: 平面の色を示す文字列。例: 'red', 'blue'。
34 :type color: str
35 :param alpha: 平面の透明度 (0.0から1.0)。
36 :type alpha: float
37 :param label: 平面を示す凡例ラベル文字列。例: r'$(110)$'。
38 :type label: str
39 :returns: None
40 """
41
42 grid_range = np.linspace(-1.5, 1.5, 50)
43
44 if l != 0:
45 xx, yy = np.meshgrid(grid_range, grid_range)
46 zz = (1 - h * xx - k * yy) / l
47 zz[(zz < -1.5) | (zz > 1.5)] = np.nan
48 ax.plot_surface(xx, yy, zz, color=color, alpha=alpha)
49
50 elif k != 0 and h != 0:
51 xx_plane, zz_plane = np.meshgrid(grid_range, grid_range)
52 yy_plane = (1 - h * xx_plane) / k
53 yy_plane[(yy_plane < -1.5) | (yy_plane > 1.5)] = np.nan
54 ax.plot_surface(xx_plane, yy_plane, zz_plane, color=color, alpha=alpha)
55
56 elif h != 0 and k == 0 and l == 0:
57 yy_plane, zz_plane = np.meshgrid(grid_range, grid_range)
58 xx_plane = np.zeros_like(yy_plane)
59 ax.plot_surface(xx_plane, yy_plane, zz_plane, color=color, alpha=alpha)
60
61 elif h == 0 and k != 0 and l == 0:
62 xx_plane, zz_plane = np.meshgrid(grid_range, grid_range)
63 yy_plane = np.zeros_like(xx_plane)
64 ax.plot_surface(xx_plane, yy_plane, zz_plane, color=color, alpha=alpha)
65
66 elif h == 0 and k == 0 and l != 0:
67 xx_plane, yy_plane = np.meshgrid(grid_range, grid_range)
68 zz_plane = np.zeros_like(xx_plane)
69 ax.plot_surface(xx_plane, yy_plane, zz_plane, color=color, alpha=alpha)
70
71 else:
72 print(f"Warning: Cannot plot plane ({h}{k}{l})")
73
74 ax.plot([], [], [], color=color, label=label, alpha=alpha)
75
76
77def main():
78 """
79 概要: 立方晶系の結晶面と[001]ゾーン軸を3Dで可視化し、画像を保存します。
80 詳細説明:
81 matplotlibを使用して3Dプロットを設定し、以下の要素を描画します。
82 - 3次元の軸とプロット範囲の設定。
83 - [001]ゾーン軸とそれに属する複数の結晶面(例: (110), (120), (010) など)。
84 - 各結晶面の法線ベクトル。
85 - 凡例とタイトル。
86 最終的に生成されたプロットは 'cubic_planes_001_zone.png' というファイル名で保存され、
87 画面にも表示されます。
88 :returns: None
89 """
90 fig = plt.figure(figsize=(10, 8))
91 ax = fig.add_subplot(111, projection='3d')
92
93 plot_limit = 1.5
94 ax.set_xlim([-plot_limit, plot_limit])
95 ax.set_ylim([-plot_limit, plot_limit])
96 ax.set_zlim([-plot_limit, plot_limit])
97
98 ax.set_xlabel('a')
99 ax.set_ylabel('b')
100 ax.set_zlabel('c')
101 ax.set_title('Cubic Crystal Planes with [001] Zone Axis')
102
103 zone_axis = np.array([0, 0, 1])
104 ax.quiver(0, 0, 0, zone_axis[0], zone_axis[1], zone_axis[2],
105 color='black', length=1.2, arrow_length_ratio=0.1)
106 ax.text(zone_axis[0] * 1.3, zone_axis[1] * 1.3, zone_axis[2] * 1.3,
107 r'$[001]$ Zone Axis', color='black')
108
109 planes_data = [
110 {'hkl': (1, 1, 0), 'color': 'red', 'label': r'$(110)$'},
111 {'hkl': (1, 2, 0), 'color': 'blue', 'label': r'$(120)$'},
112 {'hkl': (0, 1, 0), 'color': 'green', 'label': r'$(010)$'},
113 {'hkl': (1, -2, 0), 'color': 'purple', 'label': r'$(1\bar{2}0)$'},
114 {'hkl': (1, -1, 0), 'color': 'orange', 'label': r'$(1\bar{1}0)$'}
115 ]
116
117 for plane_info in planes_data:
118 h, k, l = plane_info['hkl']
119 color = plane_info['color']
120 label = plane_info['label']
121
122 plot_plane(ax, h, k, l, color, alpha=alpha, label=label)
123
124 normal_vector = np.array([h, k, l])
125 if np.linalg.norm(normal_vector) > 0:
126 normal_vector_scaled = normal_vector / np.linalg.norm(normal_vector) * 0.8
127 ax.quiver(0, 0, 0,
128 normal_vector_scaled[0],
129 normal_vector_scaled[1],
130 normal_vector_scaled[2],
131 color=color, linestyle='--',
132 length=0.8, arrow_length_ratio=0.2)
133
134 ax.text(normal_vector_scaled[0] * 1.1,
135 normal_vector_scaled[1] * 1.1,
136 normal_vector_scaled[2] * 1.1,
137 label + ' normal', color=color)
138
139 ax.legend()
140 plt.tight_layout()
141 plt.savefig('cubic_planes_001_zone.png')
142 plt.show()
143
144
145if __name__ == "__main__":
146 main()