zone_axes.py ダウンロード/コピー

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()