ドキュメント: bz_draw.py

概要

bz_draw.py は、結晶学的パラメータに基づいて第一ブリルアンゾーン(逆空間)またはウィグナー・ザイツセル(実空間)を3Dで可視化するためのPythonスクリプトです。

このスクリプトは以下の機能を提供します。

  • 指定された結晶学的パラメータと格子タイプに基づいた第一ブリルアンゾーンまたはウィグナー・ザイツセルの描画。

  • 周囲の周期的なセルをタイリング表示する機能。

  • 逆空間の場合、seekpath ライブラリを利用した高対称点のパス表示。

  • インタラクティブなパラメータ調整機能(スライダーと「Apply」ボタン)による格子定数 a, b, c の動的な変更と再描画。

インストール

bz_draw.py を実行するには、以下の非標準ライブラリが必要です。

  • numpy

  • matplotlib

  • scipy

  • seekpath

これらのライブラリは pip を使用してインストールできます。

pip install numpy matplotlib scipy seekpath

seekpath は内部で spglib に依存しており、spglib の一部のバージョンで発生する非推奨警告を無視するように、スクリプトの冒頭で設定されています。

使い方

コマンドライン引数

bz_draw.py は以下のコマンドライン引数をサポートしています。

  • --space {reciprocal,real}

    • 描画する空間タイプを選択します。

    • reciprocal: 第一ブリルアンゾーンを描画します。seekpath を使用して高対称点も表示されます。

    • real: 実空間のウィグナー・ザイツセルを描画します。

    • デフォルト値: reciprocal

  • --lattice <str>

    • 格子タイプを指定します。

    • 利用可能な値の例: P, SC, I, BCC, F, FCC, A, B, C

    • デフォルト値: P

  • --a <float>

    • 格子定数 a を指定します (Å)。

    • デフォルト値: 1.0

  • --b <float>

    • 格子定数 b を指定します (Å)。

    • デフォルト値: 1.0

  • --c <float>

    • 格子定数 c を指定します (Å)。

    • デフォルト値: 1.0

  • --alpha <float>

    • 角度 alpha を指定します (度)。

    • デフォルト値: 90.0

  • --beta <float>

    • 角度 beta を指定します (度)。

    • デフォルト値: 90.0

  • --gamma <float>

    • 角度 gamma を指定します (度)。

    • デフォルト値: 90.0

  • --n-shell <int>

    • Voronoi 計算のために考慮する格子点または逆格子点の範囲を指定します。この値が大きいほど、より多くの点が計算に用いられます。

    • デフォルト値: 3

  • --tile-nx <int>

    • x軸方向のタイルの最大数を指定します (0で非表示)。

    • デフォルト値: 0

  • --tile-ny <int>

    • y軸方向のタイルの最大数を指定します (0で非表示)。

    • デフォルト値: 0

  • --tile-nz <int>

    • z軸方向のタイルの最大数を指定します (0で非表示)。

    • デフォルト値: 0

  • --tile-rmax <float>

    • タイル描画の半径上限を指定します(中心から距離 r <= rmax のセルのみ描画)。

    • None または0以下の場合は、距離による制限はありません。

    • デフォルト値: None

  • --plot-limit <float>

    • 軸の表示範囲を強制的に [-L, L] に制限します(内部座標)。

    • デフォルト値: None

  • --tile-color-mode {checker,byindex,distance}

    • タイルの色付けモードを選択します。

    • checker: チェッカーボード状の色分け。

    • byindex: ハッシュ値に基づく色分け。

    • distance: 原点からの距離に応じたグラデーション。

    • デフォルト値: checker

  • --fade-power <float>

    • 距離に応じた透明度フェードの指数を指定します (例: 1.0=線形, 2.0=二乗)。

    • デフォルト値: 1.0

  • --no-outside-points

    • セル外部の格子点または逆格子点を表示しないようにします。

    • このオプションが指定された場合、外部点は描画されません。

  • --no-highlight-face-points

    • セルの面を定義する点を強調表示しないようにします。

    • このオプションが指定された場合、面を定義する点は強調表示されません。

  • --no-connectors

    • 面を定義する点と原点を結ぶ破線を描画しないようにします。

    • このオプションが指定された場合、破線は描画されません。

  • --no-kpath

    • 高対称点パスを描画しないようにします(reciprocal 空間の場合のみ有効)。

    • このオプションが指定された場合、パスは描画されません。

  • --label-fontsize <int>

    • 高対称点ラベルのフォントサイズを指定します。

    • デフォルト値: 10

  • --interactive-apply

    • スライダーと「Apply」ボタンで再描画するインタラクティブモードを有効にします。

    • このオプションが指定された場合、対話モードで実行されます。

  • --save <str>

    • (一括描画時のみ)画像保存パスを指定します。

    • 注: 現在のコード実装では、この引数は解析されますが、ファイルへの保存機能はコードからは確認できません。

    • デフォルト値: None

例:

第一ブリルアンゾーンを格子定数 a=3.0 で表示し、周囲のタイルを x 方向に1シェル分表示します。

python bz_draw.py --a 3.0 --tile-nx 1 --space reciprocal

ウィグナー・ザイツセルを体心立方格子 (BCC) で表示します。

python bz_draw.py --lattice BCC --space real

対話モード

--interactive-apply オプションを使用して bz_draw.py を実行すると、Matplotlibのウィンドウにスライダーと「Apply」ボタンが表示され、格子定数 a, b, c をインタラクティブに調整できます。

  • スライダー:

    • a, b, c のスライダーを動かすことで、それぞれの格子定数の値を変更できます。

    • スライダーを動かしただけでは描画は更新されません。

  • 「Apply」ボタン:

    • スライダーで値を調整した後、「Apply」ボタンをクリックすると、現在のスライダーの値に基づいてシーンが再描画されます。

    • この再描画では、seekpath の結果がキャッシュされるため、特に逆空間の描画が高速に更新されます。

    • 描画中はボタンの表示が「Redrawing...」に変わり、処理中であることを示します。

例:

対話モードで第一ブリルアンゾーンを描画します。

python bz_draw.py --interactive-apply --space reciprocal

コード解説

非標準ライブラリ

bz_draw.py は以下の非標準ライブラリを利用しています。

  • numpy:

    • 数値計算、特にベクトルや行列の操作、三角関数、線形代数計算に使用されます。格子基底の構築や点群の生成などで利用されます。

  • matplotlib:

    • グラフ描画ライブラリ。3Dプロットの作成、描画オブジェクトの管理、GUI要素(スライダー、ボタン)の表示に使用されます。

  • scipy:

    • 科学計算ライブラリ。特に scipy.spatial.Voronoi を使用して、第一ブリルアンゾーンやウィグナー・ザイツセルをボロノイ図として計算するために用いられます。

  • seekpath:

    • 結晶の原始格子から高対称点とそのパスを自動的に決定するために使用されます。これにより、第一ブリルアンゾーンのパス表示が可能です。seekpath は内部的に spglib に依存しています。

主要関数

build_conventional_basis(a, b, c, alpha, beta, gamma)

  • 目的: 従来の結晶学的パラメータ(格子定数と角度)から直交座標系における格子基底ベクトルを構築します。最初の基底ベクトルは x 軸に沿い、2番目の基底ベクトルは xy 平面に配置され、3番目の基底ベクトルは正の z 成分を持つように配置されます。

  • 引数:

    • a (float): 格子定数 a (Å)。

    • b (float): 格子定数 b (Å)。

    • c (float): 格子定数 c (Å)。

    • alpha (float): 角度 alpha (度)。

    • beta (float): 角度 beta (度)。

    • gamma (float): 角度 gamma (度)。

  • 戻り値:

    • numpy.ndarray: 構築された3x3の格子基底行列。各列が基底ベクトル (a_vec, b_vec, c_vec) を表します。

primitive_from_centering(A_conv, lattice_tag)

  • 目的: 従来の格子基底と格子タイプから原始格子基底を計算します。与えられた従来の格子基底に対し、指定されたセンタリングタイプ(P, I, Fなど)に対応する変換行列を適用して原始格子基底を導出します。

  • 引数:

    • A_conv (numpy.ndarray): 従来の3x3格子基底行列(列が基底ベクトル)。

    • lattice_tag (str): 格子タイプを示す文字列 (例: 'P', 'I', 'F', 'SC', 'BCC', 'FCC', 'A', 'B', 'C')。

  • 戻り値:

    • numpy.ndarray: 原始3x3格子基底行列(列が原始基底ベクトル)。

  • 例外:

    • ValueError: 未知の格子タイプまたは未サポートの格子タイプが指定された場合。

order_polygon_vertices_on_plane(P)

  • 目的: 平面上にある多角形の頂点を反時計回りに並べ替えるインデックスを返します。頂点の重心を計算し、SVD(特異値分解)を用いて平面の法線ベクトルを決定します。その後、基準ベクトルと法線に垂直なベクトルを生成し、これらの座標系で各頂点の角度を計算してソートします。この順序はMatplotlibで多角形を描画する際に重要です。

  • 引数:

    • P (numpy.ndarray): 多角形の頂点群を表すNx3のNumPy配列。

  • 戻り値:

    • numpy.ndarray: 頂点を反時計回りに並べ替えるためのインデックスの配列。

reciprocal_points_from_basis(B, n)

  • 目的: 与えられた基底ベクトルとシェル数に基づいて、格子点または逆格子点の配列を生成します。各基底ベクトルの整数倍(-nからnまで)の組み合わせで、中心の点を含む広範囲の点を生成します。これはVoronoi図の計算に必要な点群を提供します。

  • 引数:

    • B (numpy.ndarray): 3x3の基底ベクトル行列(列が基底ベクトル)。

    • n (int): 各基底ベクトルに沿って考慮するシェル数(例: n=1 なら -1, 0, 1 の係数を使用)。

  • 戻り値:

    • numpy.ndarray: 生成された点群のNx3のNumPy配列。

get_cell_faces_and_neighbors(vor, point_index)

  • 目的: Voronoi図の中心点に関連する面の頂点インデックスと隣接点のインデックスを取得します。Voronoi オブジェクトの ridge_pointsridge_vertices を走査し、指定された点に関連する有限な面(-1を含まない、3頂点以上)を抽出します。

  • 引数:

    • vor (scipy.spatial.Voronoi): scipy.spatial.Voronoi オブジェクト。

    • point_index (int): 中心となる点の、Voronoi計算に用いた点群におけるインデックス。

  • 戻り値:

    • tuple[list[numpy.ndarray], list[int]]: (faces, neighbors) のタプル。faces は各面の頂点インデックスのリストのリスト、neighbors は各面に対応する隣接点のインデックスのリスト。

cell_polygons(vor, point_index)

  • 目的: Voronoi図の中心点に関連する多角形(セル面)と隣接点のリストを生成します。get_cell_faces_and_neighbors() を利用して面の頂点インデックスを取得し、order_polygon_vertices_on_plane() で頂点を反時計回りに順序付けて多角形オブジェクトを構築します。

  • 引数:

    • vor (scipy.spatial.Voronoi): scipy.spatial.Voronoi オブジェクト。

    • point_index (int): 中心となる点の、Voronoi計算に用いた点群におけるインデックス。

  • 戻り値:

    • tuple[list[numpy.ndarray], list[int]]: (polygons, neighbors) のタプル。polygons は各面の頂点座標のNx3 NumPy配列のリスト、neighbors は各面に対応する隣接点のインデックスのリスト。

_key_from_Aprim(A_prim, symprec)

  • 目的: 原始格子基底行列と対称操作の許容誤差からキャッシュキーを生成します。functools.lru_cache で使用するためのキーです。浮動小数点数の比較を安定させるため、行列の要素は指定された精度で丸められます。

  • 引数:

    • A_prim (numpy.ndarray): 原始3x3格子基底行列(列が基底ベクトル)。

    • symprec (float): 対称操作の許容誤差。

  • 戻り値:

    • tuple: キャッシュキーとして使用されるタプル。

_seekpath_cached(key)

  • 目的: seekpath.get_path() を呼び出し、結果をキャッシュする内部関数です。functools.lru_cache デコレータにより、同じ入力(キャッシュキー)に対しては実際に seekpath を呼び出さずに、キャッシュされた結果を返します。これにより、インタラクティブな描画での再計算を高速化します。

  • 引数:

    • key (tuple): _key_from_Aprim() で生成されたキャッシュキー。

  • 戻り値:

    • tuple[numpy.ndarray, dict[str, numpy.ndarray], list[tuple[str, str]]]: (Bstd, kpts_abs, path) のタプル。Bstd は標準逆格子基底行列、kpts_abs は高対称点の絶対座標辞書、path は高対称点パスのリスト。

bz_and_kpath_from_seekpath_cached(A_prim, symprec=1e-7)

  • 目的: seekpath を用いて、第一ブリルアンゾーンの標準逆格子基底、高対称点、およびパスを取得します。_seekpath_cached() を通じて functools.lru_cache によるキャッシュを利用するため、同じ原始格子基底に対しては seekpath の計算がスキップされ、高速に結果を返します。

  • 引数:

    • A_prim (numpy.ndarray): 原始3x3格子基底行列(列が基底ベクトル)。

    • symprec (float): 対称操作の許容誤差。

  • 戻り値:

    • tuple[numpy.ndarray, dict[str, numpy.ndarray], list[tuple[str, str]]]: (Bstd, kpts_abs, path) のタプル。Bstd は標準逆格子基底行列、kpts_abs は高対称点の絶対座標辞書、path は高対称点パスのリスト。

pretty_label(lbl)

  • 目的: 高対称点のラベルを整形します(例: "GAMMA" を "Γ" に変換)。

  • 引数:

    • lbl (str): 整形前の高対称点ラベル文字列。

  • 戻り値:

    • str: 整形された高対称点ラベル文字列。

color_checker(i,j,k)

  • 目的: 三次元インデックス (i, j, k) に基づいてチェッカーボード状の色を返します。各インデックスの偶奇性から0から7までのインデックスを生成し、定義されたパレットから色を選択します。

  • 引数:

    • i (int): 第1軸方向のインデックス。

    • j (int): 第2軸方向のインデックス。

    • k (int): 第3軸方向のインデックス。

  • 戻り値:

    • str: HEX形式の色コード文字列 (例: '#1f77b4')。

color_hash(i,j,k, cmap=plt.cm.tab20)

  • 目的: 三次元インデックス (i, j, k) に基づいてハッシュ値から色を生成します。与えられた整数インデックスから一意のハッシュ値を生成し、そのハッシュ値を正規化して指定されたカラーマップから色を抽出します。

  • 引数:

    • i (int): 第1軸方向のインデックス。

    • j (int): 第2軸方向のインデックス。

    • k (int): 第3軸方向のインデックス。

    • cmap (matplotlib.colors.Colormap): 使用するMatplotlibカラーマップ。

  • 戻り値:

    • tuple: RGBA形式の色タプル。

color_distance(t, rmax, cmap=plt.cm.viridis)

  • 目的: 原点からの距離に基づいてグラデーション色を返します。点の位置ベクトル t の原点からの距離を計算し、rmax で正規化して指定されたカラーマップ cmap から色を抽出します。

  • 引数:

    • t (numpy.ndarray): 点の3D座標ベクトル。

    • rmax (float or None): 色のグラデーションの最大半径。これを超えると色が飽和します。None または0以下の場合は常に最大値の色を返します。

    • cmap (matplotlib.colors.Colormap): 使用するMatplotlibカラーマップ。

  • 戻り値:

    • tuple: RGBA形式の色タプル。

alpha_fade(t, rmax, a_min=0.06, a_max=0.22, power=1.0)

  • 目的: 原点からの距離に基づいて透明度をフェードさせる値を返します。点の位置ベクトル t の原点からの距離が rmax に近づくにつれて、透明度が a_max から a_min へとフェードアウトするように計算されます。power パラメータでフェードの非線形性を調整できます。

  • 引数:

    • t (numpy.ndarray): 点の3D座標ベクトル。

    • rmax (float or None): 透明度フェードの最大半径。これを超えると透明度は a_min に近づきます。None または0以下の場合は常に a_max を返します。

    • a_min (float): 最小透明度 (0.0=完全透明, 1.0=完全不透明)。

    • a_max (float): 最大透明度 (0.0=完全透明, 1.0=完全不透明)。

    • power (float): フェードの指数(例: 1.0=線形, 2.0=二乗)。

  • 戻り値:

    • float: 計算された透明度の値。

plot_once(args)

  • 目的: 指定されたパラメータに基づいて、第一ブリルアンゾーンまたはウィグナー・ザイツセルを一度だけ描画します。結晶学的パラメータから格子基底を構築し、SceneManager を使用してシーンを描画し、結果をMatplotlibウィンドウに表示します。

  • 引数:

    • args (argparse.Namespace): コマンドライン引数を格納する argparse.Namespace オブジェクト。

  • 例外:

    • SystemExit: seekpath の実行に失敗した場合。

plot_interactive_apply(args)

  • 目的: スライダーと「Apply」ボタンを備えたインタラクティブな描画インターフェースを提供します。a, b, c の格子定数をスライダーで調整でき、「Apply」ボタンをクリックしたときにのみシーンが再描画されます。seekpath の結果はキャッシュされるため、再描画時の計算コストが削減され、高速な更新が可能です。

  • 引数:

    • args (argparse.Namespace): コマンドライン引数を格納する argparse.Namespace オブジェクト。

main()

  • 目的: プログラムのエントリーポイントです。コマンドライン引数を解析し、ユーザーの選択に応じて第一ブリルアンゾーンまたはウィグナー・ザイツセルの描画機能(一度きりの描画またはインタラクティブな描画)を呼び出します。

クラス

SceneManager

  • 目的: Matplotlibの3Dシーンを管理し、描画オブジェクト(アーティスト)の追加、クリア、更新を行います。特に、描画のたびに既存のオブジェクトを効率的に削除し、新しいオブジェクトを追加することで、インタラクティブな描画でのちらつきを抑え、高速な更新を可能にします。

  • メソッド:

    • __init__(self, args)

      • 目的: シーンマネージャを初期化します。Matplotlibの Figure と3D Axes を作成し、以前の描画オブジェクトを保持するためのリストを準備します。

      • 引数:

        • args (argparse.Namespace): コマンドライン引数を格納する argparse.Namespace オブジェクト。

    • clear_artists(self)

      • 目的: 前回描画したすべてのMatplotlibアーティストをシーンから削除します。これにより、Axes 自体は維持しつつ、内容だけを更新することができます。

    • add_artist(self, *objs)

      • 目的: 新しいMatplotlibアーティストを管理リストに追加します。描画されたアーティストは、後で clear_artists() メソッドで効率的に削除できるようにこのリストに格納されます。リストやタプルの形式で複数のアーティストを渡すことも可能です。

      • 引数:

        • objs (matplotlib.artist.Artist or list or tuple): シーンに追加するMatplotlibアーティストオブジェクト(一つまたは複数)。

    • draw_scene(self, space, A_prim, Bstd, n_shell, tile_nx, tile_ny, tile_nz, tile_rmax, show_outside_points, highlight_face_points, draw_connectors_to_faces, draw_kpath, color_mode='checker', fade_power=1.0, kpts_abs=None, kpath=None, label_fontsize=10)

      • 目的: 第一ブリルアンゾーンまたはウィグナー・ザイツセル、およびそのタイリングされたビューを描画します。空間タイプ(実空間または逆空間)に応じてVoronoi図を構築し、中心セル、面生成点、周期タイル、高対称点とパス(逆空間の場合のみ)を描画します。既存のアーティストをクリアし、新しいアーティストを追加する差分更新方式を採用しています。

      • 引数:

        • space (str): 描画する空間タイプ ('reciprocal' または 'real')。

        • A_prim (numpy.ndarray): 原始3x3格子基底行列(実空間の基底)。

        • Bstd (numpy.ndarray or None): 標準逆格子3x3基底行列(逆空間の基底、2π因子を含む)。

        • n_shell (int): Voronoi計算のために考慮する格子点/逆格子点のシェル数。

        • tile_nx (int): x軸方向のタイルの最大数(0で非表示)。

        • tile_ny (int): y軸方向のタイルの最大数(0で非表示)。

        • tile_nz (int): z軸方向のタイルの最大数(0で非表示)。

        • tile_rmax (float or None): タイル描画の半径上限(中心から距離 r <= rmax のセルのみ描画)。None または0以下の場合、距離による制限なし。

        • show_outside_points (bool): セル外部の格子点/逆格子点を表示するかどうか。

        • highlight_face_points (bool): セルの面を定義する点を強調表示するかどうか。

        • draw_connectors_to_faces (bool): 面を定義する点と原点を結ぶ破線を描画するかどうか。

        • draw_kpath (bool): 高対称点パスを描画するかどうか(reciprocal 空間のみ有効)。

        • color_mode (str): タイルの色付けモード ('checker', 'byindex', 'distance')。

        • fade_power (float): 距離に応じた透明度フェードの指数。

        • kpts_abs (dict[str, numpy.ndarray] or None): 高対称点の絶対座標を格納した辞書 (reciprocal 空間の場合のみ)。

        • kpath (list[tuple[str, str]] or None): 高対称点パスのリスト (reciprocal 空間の場合のみ)。

        • label_fontsize (int): 高対称点ラベルのフォントサイズ。

データ構造

  • 格子基底行列 (A_conv, A_prim, Bstd):

    • 3x3の numpy.ndarray で、各列が基底ベクトルを表します。例えば、A_prim[:,0] が第一原始基底ベクトルとなります。

  • 高対称点辞書 (kpts_abs):

    • キーが文字列のラベル(例: 'GAMMA', 'X')、値が対応する3D座標を保持する numpy.ndarray です。

  • 高対称点パスリスト (kpath):

    • タプルのリストで、各タプルはパスを構成する2つの高対称点ラベル(文字列)を含みます。例えば、[('GAMMA', 'X'), ('X', 'M')] のように表現されます。

入出力

入力

  • コマンドライン引数:

    • プログラム起動時に与えられる結晶学的パラメータ、描画オプション、表示設定など。

  • 対話モードでのスライダー操作:

    • --interactive-apply オプションが指定された場合、ユーザーはMatplotlibウィンドウ内のスライダーを操作して格子定数 a, b, c を変更できます。

出力

  • Matplotlib 3Dプロットウィンドウ:

    • 指定されたパラメータに基づいて描画された第一ブリルアンゾーンまたはウィグナー・ザイツセル、および周囲のタイルが3Dグラフィックとしてリアルタイムに表示されます。

  • 画像ファイル (未実装):

    • --save オプションは引数として提供されていますが、現在のコードの実装では、指定されたパスに画像を保存する機能は確認できません。