# plot3d.py — VASP Volumetric データ 3D 可視化ツール

`plot3d.py` は VASP の CHGCAR / LOCPOT / ELFCAR など **volumetric データ**を、
- **3D 等値面 (isosurface)**
- **点群 (dots / scatter)**
- **断面スライス（XY・YZ・ZX）**

で同時に可視化するための Python スクリプトです。**非直交格子（斜方・六方など）にも対応**しています。

---

## 1. プログラムの動作

1. **CHGCAR 読み込み**
   - POSCAR 部分（タイトル、スケール、格子ベクトル、原子種・個数、座標種別、原子座標）を読み込み、空行をスキップしてから体積データのグリッドサイズを読み込みます。
   - 体積データ（電荷密度など）を Fortran 順 (`order='F'`) で 3D 配列に復元します。

2. **分率空間 → 直交座標変換**
   - Marching cubes は直交格子前提のため、**分率空間で等値面抽出→格子行列（a,b,c）で直交座標に写像**します。
   - スライスは **分率一定面（fx, fy, fz のいずれか）を固定**し、各面を直交座標に変換して `plot_surface` で貼り付けます（色はスライス値）。

3. **描画モード**
   - `--mode iso` : 等値面のみ表示
   - `--mode dots` : 点群のみ表示
   - `--mode both` : **等値面 + 断面スライス** を同時表示（推奨）

4. **高速化オプション**
   - `--ds DSX DSY DSZ` : 各軸で **ダウンサンプリング**（例：`--ds 2 2 2`）
   - `--float32` : 配列型を `float32` にしてメモリ・速度を節約
   - 等値面：`--edge none`、低アルファ、レベル数を控えめに
   - dots：`--quantile` で上位のみ、`--max-points` で点数上限、`--subsample` で間引き

---

## 2. 必要な非標準ライブラリとインストール方法

- Python 3.9+ 推奨
- 必須ライブラリ
  - `numpy`
  - `matplotlib`
  - `scikit-image`（`skimage.measure.marching_cubes` を使用）
- 付属ライブラリ
  - **`tkPlot3d.py`**（本ツールが依存）を `plot3d.py` と同じフォルダに置いてください

### インストール例 (Windows / Linux / macOS)

```bash
pip install numpy matplotlib scikit-image
```

> 注: 環境により `pip3` を使用する場合があります。仮想環境を推奨します。

---

## 3. 使い方 (Usage)

```bash
python plot3d.py CHGCAR [--mode {iso,dots,both}] 
                        [--levels L1 L2 ... | --nlevels N]
                        [--alpha A] [--edge COLOR] [--lw WIDTH] [--no-legend]
                        [--cutoff C] [--quantile Q] [--subsample K] [--max-points M]
                        [--size S] [--cmap NAME]
                        [--slice-xy fz1 fz2 ...] [--slice-yz fx1 fx2 ...] [--slice-zx fy1 fy2 ...]
                        [--slice-cmap NAME] [--slice-alpha A]
                        [--float32] [--ds DSX DSY DSZ]
                        [--ortho] [--pad P] [--save OUTFILE] [--title TITLE]
```

### 主なオプション
- **基本**
  - `infile` : CHGCAR/LOCPOT/ELFCAR のファイルパス
  - `--mode` : `iso`（等値面）/`dots`（点群）/`both`（等値面+スライス）
  - `--save` : 画像として保存（例：`--save out.png`）
  - `--title` : 図タイトルを上書き

- **等値面**
  - `--levels L1 L2 ...` : しきい値を明示指定（絶対値）
  - `--nlevels N` : データの min/max を避けた範囲で等分割自動生成（端レベル除外）
  - `--alpha A` : 面の透明度（0〜1）
  - `--edge COLOR` : エッジ色（高速化には `none` 推奨）
  - `--lw WIDTH` : エッジ線幅

- **点群 (dots)**
  - `--cutoff C` : 絶対値しきい（`>= C` の点だけ描画）
  - `--quantile Q` : 上位分位（例：`0.98` → 上位2%だけ）
  - `--subsample K` : K点ごとに 1 点の間引き
  - `--max-points M` : 表示点数の最大数
  - `--size S` : マーカーサイズ
  - `--cmap NAME` : カラーマップ名（例：`viridis`, `plasma`, `inferno` など）

- **スライス**
  - `--slice-xy fz...` : `fz`（分率 0〜1）一定の XY 面を追加
  - `--slice-yz fx...` : `fx` 一定の YZ 面
  - `--slice-zx fy...` : `fy` 一定の ZX 面
  - `--slice-cmap NAME` : スライス面のカラーマップ
  - `--slice-alpha A` : スライス面の透明度

- **表示・高速化**
  - `--float32` : 配列を `float32` 化して省メモリ＆高速
  - `--ds DSX DSY DSZ` : 各軸のダウンサンプリング（例：`--ds 2 2 2`）
  - `--ortho` : 直交投影（環境により軽くなる場合あり）
  - `--pad P` : 軸範囲に余白を付与（Å）

---

## 4. 実行例

### 4.1 等値面 + 断面（z 分率 0.25, 0.75 の 2 面）
```bash
python plot3d.py CHGCAR --mode both --nlevels 3 --slice-xy 0.25 0.75 --slice-alpha 0.55
```

### 4.2 等値面 3 本 + 3 方向スライス（x=0.5, y=0.33, z=0.66）
```bash
python plot3d.py CHGCAR --mode both --levels 0.5 1.0 1.5 \
  --slice-yz 0.5 --slice-zx 0.33 --slice-xy 0.66 --slice-cmap plasma --slice-alpha 0.6
```

### 4.3 軽量表示（ダウンサンプリング & float32）
```bash
python plot3d.py CHGCAR --mode both --nlevels 3 \
  --slice-xy 0.5 --slice-alpha 0.5 \
  --ds 2 2 2 --float32 --edge none
```

### 4.4 点群（上位 2% のみ・10 万点上限・軽量）
```bash
python plot3d.py CHGCAR --mode dots --quantile 0.98 --max-points 100000 \
  --subsample 2 --size 0.3 --float32 --ds 2 2 2 --no-legend
```

---

## 5. トラブルシューティング

- **`IndexError: index ... is out of bounds for axis ...`**  
  - `plot_surface` の `facecolors` 形状不一致が原因。最新版ではセル中心色 `(M-1, N-1, 4)` を渡すように修正済み。
  - もし再発する場合は、`tkPlot3d.py` の `plot_surface3d` が `ax.plot_surface(X, Y, Z, facecolors=facecolors, ...)` を受け取ることを確認。

- **描画が重い / 固まる**  
  - `--ds 2 2 2` や `--ds 3 3 3` を試す
  - `--float32` を付ける
  - 等値面の `--nlevels` を小さくする、`--edge none`、`--alpha` をやや下げる
  - dots なら `--quantile`, `--max-points`, `--subsample` で点数を減らす

- **非直交格子で形が崩れる**  
  - 本ツールは**分率空間での処理→格子行列で直交座標へ変換**を採用。問題があれば該当 CHGCAR の先頭（格子行列）と `--ds` 設定をご確認ください。

---

## 6. バージョン管理のメモ
- `render_slice_plane` の YZ 面での `vals` の転置 `.T` は不要（形状不一致の原因）
- スライスの `facecolors` はセル平均から作る（(M-1,N-1,4)）

---

## 7. 謝辞
- `tkPlot3d.py` をお借りしました。Poly3DCollection や色処理の補助関数により、実装を簡潔にできました。
