# bz_draw.py — 任意格子から第一ブリルアンゾーン / Wigner–Seitz を描く教材ツール

**bz_draw.py** は、与えた実空間格子から  
- 逆格子の **第一ブリルアンゾーン (BZ)**、または  
- 実空間の **Wigner–Seitz セル**  
を **Voronoi** 幾何で生成・可視化するスクリプトです。教材向けに見やすさ・理解補助を重視しています。

## できること（特徴）
- 面を **一枚の多角形** として描画（内部の三角分割エッジを出さない）
- **高対称点（Γ, X, L, W, …）の自動ラベル** と **標準 k-path**（SeeK-path）
- セルを **x/y/z 方向に周期タイル**表示（フェード・色分け対応）
- **距離で透明度を変化**（遠いセルほど薄く）
- **セルごとに色分け**（チェッカー / ハッシュ / 距離グラデーション）
- **球半径 `--tile-rmax`** 以内のみ描画（ごちゃつき抑制）
- **Apply ボタン**を押したときだけ再描画（インタラクティブ）。再描画中はボタン表示が **“Redrawing…”**
- **SeeK-path 結果をキャッシュ**して再計算を最小化
- 任意の格子：`a,b,c` と角度 `α,β,γ`、および **SC/P, BCC/I, FCC/F, A/B/C（基底面心）** を指定可能
- BZ（逆格子）と WS（実空間）のどちらも描画可

---

## 必要な外部ライブラリ
- [NumPy](https://numpy.org/)
- [SciPy](https://scipy.org/)（`scipy.spatial.Voronoi`）
- [Matplotlib](https://matplotlib.org/)
- [SeeK-path](https://seekpath.readthedocs.io/)（内部で **spglib** を使用）

### インストール
```bash
# 推奨: 仮想環境の上で
python -m venv .venv
# (Windows) .venv\Scripts\activate
# (macOS/Linux) source .venv/bin/activate

pip install --upgrade pip
pip install numpy scipy matplotlib seekpath
```

> メモ: SeeK-path 実行時に spglib の `DeprecationWarning`（辞書スタイル非推奨）が出ることがあります。動作に支障はありません。必要なら下記で **その警告だけ** 抑制できます。
> ```python
> import warnings
> warnings.filterwarnings(
>   "ignore",
>   category=DeprecationWarning,
>   module=r"spglib\.spglib",
>   message=r"^dict interface \(SpglibDataset\['.*'\]\) is deprecated"
> )
> ```

---

## 使い方（Usage）
```bash
python bz_draw.py [options]
```

### 主なオプション
**空間の選択**
- `--space {reciprocal,real}`  
  `reciprocal`: 第一 BZ（既定。高対称点＆k-path を表示）  
  `real`: 実空間 Wigner–Seitz セル

**格子指定**
- `--lattice {P,SC,I,BCC,F,FCC,A,B,C}`（既定 `P`）  
  - `P/SC`: 単純格子  
  - `I/BCC`: 体心  
  - `F/FCC`: 面心  
  - `A/B/C`: 基底面心（A=bc面心, B=ac面心, C=ab面心）
- `--a --b --c`（既定 1.0）: 格子長
- `--alpha --beta --gamma`（既定 90）: 角度（度）  
  `alpha=∠(b,c), beta=∠(c,a), gamma=∠(a,b)`

**Voronoi 計算の安定化**
- `--n-shell INT`（既定 3）: 周囲に並べる格子点の範囲（大きいほどセルが安定）

**周期タイル描画**
- `--tile-nx --tile-ny --tile-nz`（既定 0）: ±N までタイル（候補枠）
- `--tile-rmax FLOAT` : 中心から **距離 ≤ rmax** のセルだけ描画（球カット）  
  ※ 欠ける場合は `--tile-n*` を増やしてください（目安: `nx ≳ ceil(tile_rmax/||b1||)` など）

**色分け・透明度**
- `--tile-color-mode {checker,byindex,distance}`（既定 `checker`）  
  - `checker`: 2×2×2 のチェッカーで周期性を強調  
  - `byindex`: (i,j,k) のハッシュで多数色  
  - `distance`: 距離グラデーション（`viridis`）
- `--fade-power FLOAT`（既定 1.0）: 距離フェードの指数（1=線形, 2=二乗 …）

**表示の切り替え**
- `--no-outside-points` : 周囲の格子点ドットを非表示
- `--no-highlight-face-points` : 面を作る最近接点を非表示
- `--no-connectors` : 原点 Γ から最近接点への点線を非表示
- `--no-kpath` : （逆格子モード）標準 k-path 線を非表示
- `--label-fontsize INT`（既定 10）: 高対称点ラベルのフォントサイズ

**保存 / インタラクティブ**
- `--save PATH` : 画像ファイル保存（PNG など）
- `--interactive-apply` : a,b,c の **スライダ + Apply ボタン** UI  
  - スライダ操作だけでは描画せず、**Apply** で再描画  
  - 再描画中はボタンが **“Redrawing…”** に変わり無効化  
  - SeeK-path の結果は内部キャッシュで高速化

---

## 使用例

### 1) FCC の第一 BZ をタイル表示（rmax=12、チェッカー色＋距離フェード）
```bash
python bz_draw.py --space reciprocal --lattice FCC --a 1   --tile-nx 4 --tile-ny 4 --tile-nz 4 --tile-rmax 12   --tile-color-mode checker --fade-power 1.5
```

### 2) BCC（a=3,b=4,c=5）の Wigner–Seitz セルを 2×2×2 タイル
```bash
python bz_draw.py --space real --lattice BCC --a 3 --b 4 --c 5   --alpha 90 --beta 90 --gamma 90   --tile-nx 2 --tile-ny 2 --tile-nz 2 --tile-rmax 15
```

### 3) 色を距離グラデーションに（viridis）、フェード指数=2
```bash
python bz_draw.py --space reciprocal --lattice BCC --a 1   --tile-nx 5 --tile-ny 5 --tile-nz 5 --tile-rmax 10   --tile-color-mode distance --fade-power 2
```

### 4) スライダ + **Apply** ボタンで a,b,c を更新（逆格子でも実空間でも可）
```bash
python bz_draw.py --interactive-apply --space reciprocal --lattice FCC --a 1 --b 1 --c 1   --tile-nx 3 --tile-ny 3 --tile-nz 3 --tile-rmax 10
```

---

## 動作の仕組み（ざっくり）
1. 入力の従来セル（a,b,c, α,β,γ）から **原始格子** を構成（P / I / F / A / B / C に対応）
2. `reciprocal` の場合はそれを SeeK-path に渡して  
   - **標準化された逆格子基底（2πを含む）**  
   - **高対称点ラベルと座標**  
   - **標準 k-path**  
   を取得（結果はキャッシュ）
3. 基底ベクトルの整数結合で点群を作り、中心セルまわりで **Voronoi** を実行
4. 中心セル（BZ or WS）の各面を **一枚の多角形** として描画（外周のみ線を引く）
5. 周期タイルは中心セルの面ポリゴンを平行移動して再利用（高速・安定）

---

## よくある落とし穴 / トラブルシューティング
- **`matplotlib` import 時にエラー**  
  スクリプト名を `bz2.py` にすると標準ライブラリ `bz2` と衝突します。  
  ⇒ 例: `bz_draw.py` などにリネームし、同ディレクトリの `__pycache__` を削除。
- **スライダ UI が重い / 反応が遅い**  
  `--interactive-apply` では Apply を押したときだけ再描画し、SeeK-path をキャッシュしています。  
  さらに軽くしたい場合は `--n-shell` を小さめに、または表示オプション（k-path など）を間引いてください。
- **セルが欠ける**  
  `--tile-rmax` に対して `--tile-n*` が不足している可能性。`--tile-n*` を増やしてください。

---

## ライセンス / クレジット
- このスクリプトは教育・研究用途を想定しています。  
- 高対称点と標準 k-path は **SeeK-path** の定義に従います（内部で **spglib** を使用）。

---
