# 技術スタック (Tech Stack)

## 概要 (Overview)

Fusion 360 で設計中の SmTIAS 筐体を CPU 上で光学シミュレーションし，
SmTIAS-Evaluation と互換の指標で照明均一性を評価できるようにする．

## 言語・実行環境 (Language & Runtime)

| 項目 | 採用 | 備考 |
| --- | --- | --- |
| 言語 | Python | SmTIAS-Evaluation と揃え，評価コード（`uniformity.py`）を共有しやすくするため |
| Python バージョン | 3.12（`.python-version` で固定） | Mitsuba 3 の Windows wheel が安定して配布されている範囲 |
| OS | Windows 10 / 11（主） | macOS / Linux でも理論上動作するが優先サポートしない |
| ハードウェア | CPU のみ（当面） | 将来 GPU（CUDA）への移行はオプションとして残す（後述） |

## シミュレーションコア (Simulation Core)

| 項目 | 採用 | 備考 |
| --- | --- | --- |
| シミュレータ | **Mitsuba 3**（3.8.x） | 物理ベース・モンテカルロレンダラ．Python API あり |
| バリアント (variant) | `llvm_ad_rgb` をメインで使用 | Dr.Jit + LLVM JIT による CPU 並列化．scalar より高速で AD（自動微分）対応 |
| 将来の拡張 | `llvm_ad_spectral`（スペクトル），`cuda_ad_rgb`（GPU） | 色再現性 / GPU 化の段階で切り替える |
| 必須ランタイム | LLVM-C.dll（Windows） | Dr.Jit が JIT 実行時に呼ぶ．`winget install LLVM.LLVM` で導入 |

### 採用理由

- 物理量（放射照度・配光）を素直に扱え，実測値とのキャリブレーションに向く
- BSDF（半透明散乱・拡散反射）が組み込みで揃っており，ディフューザーを既存実装で書ける
- Python API なので評価指標コードと同じスクリプトに統合できる
- 色再現性の検証に拡張する際もスペクトル変種に切替えるだけで済む

### 既存ツールとの比較（なぜ自作 Mitsuba 3 か）

本プロジェクトの本質は「きれいな絵を作る」ことではなく，**実機センサが吐く数値を物理的に再現し，実測との差の原因を切り分けられること**にある（SmTIAS は白い筐体内壁の多重反射で照明を均一化する設計のため．[SPEC_03 参照](../04_SPEC/SPEC_03_基準設計の物理構成.md)）．この性質が選定をほぼ決める．

| 候補 | ライセンス費 | 物理量の直接取得 | 評価指標コードの実機共有 | キャリブの透明性（ISP/OETF 切分け） | 拡張性（スペクトル / 自動微分） |
| --- | --- | --- | --- | --- | --- |
| 商用光学・照明シミュレータ（Ansys Speos / LightTools / Zemax OpticStudio / TracePro 等） | ✕（年額・見積もりベース） | ◯ | ✕（内部がブラックボックス） | △（センサ ISP は通常モデル化外・内部不可視） | △（製品依存） |
| 汎用 OSS レンダラ（Blender Cycles / LuxCore 等） | ◯（無償） | △（露出・トーンマップが介在） | △（Python での指標一体運用がしにくい） | △ | △ |
| **Mitsuba 3 自作（本プロジェクト採用）** | ◯（無償） | ◯（放射照度・配光をそのまま出力） | ◯（`uniformity.py` を実機系とコード共有） | ◯（交絡を 1 つずつ自前モデル化・切分け可） | ◯（variant 切替で対応） |

決め手（上記「採用理由」を補完する観点）:

- **コスト**: この種の商用照明シミュレータは買い切りでなく年額ライセンス・かつ見積もりベースで，1 シート年間数十万〜数百万円規模と一般に言われる水準．研究室での単一目的（照明均一性の事前検討）には過大投資．正確な金額はベンダー見積もり次第のため断定しないが，桁感としては妥当．
- **評価指標コードの実機共有（決定的）**: `uniformity.py` を SmTIAS-Evaluation から直接コピーし（下記「[SmTIAS-Evaluation コードの取り扱い](#minitias-evaluation-コードの取り扱い-reuse-policy)」），シミュと実測を**同一実装**で評価する．差が出れば「純粋に物理差」と断言できる．閉じた商用ツールでは内部の輝度変換・指標計算を実機系 OSS とビット一致させられず，この担保が構造的に不可能．
- **キャリブレーションの透明性**: sRGB OETF / ISP レンズシェーディング / spp / max_depth といった交絡を自前でモデル化し，一つずつ切り分けられる．実例として Step 8 では見かけ差の**約 2/3 が sRGB 符号化ドメイン不一致**だったと特定している（[SPEC_03「キャリブレーション経過」§寄与順の訂正と残差](../04_SPEC/SPEC_03_基準設計の物理構成.md)：寄与順は OETF（最大）＞ ISP レンズシェーディング ＞ 反射率）．中身が全て見える自作ならではの分析．
- **拡張性**: スペクトル変種（`llvm_ad_rgb` → spectral）への切替で色再現検証へ，自動微分（AD）で将来の逆設計（最適 LED 配置の勾配ベース探索）へ，同一基盤のまま拡張できる．

自作の代償（公平のため明記）: 物理正確性を自前で保証する責任が生じ，商用ツールの検証済みライブラリ・GUI・サポートは得られない．本プロジェクトは Step 7 で直接照度ベイクを解析解（`I·cosθ/r²`）と数 % 以内で照合し，Step 8 で実測校正を行うことでこれを担保している．残差 1.6〜1.9 倍はガンマ曲線で消さず原因（ISP レンズシェーディング等）まで含めて正直に保持しており，この透明性自体がブラックボックス商用ツールでは到達しにくい強みとなる．

## 依存管理 (Dependency Management)

| 項目 | 採用 | 備考 |
| --- | --- | --- |
| パッケージマネージャ | **uv**（Astral 製） | 高速・クロスプラットフォーム・ロックファイル付き |
| 設定ファイル | `pyproject.toml`（PEP 621） | プロジェクト依存をここに集約 |
| ロックファイル | `uv.lock` | コミット対象（再現性のため） |
| Python バージョン管理 | `uv` 内蔵（`.python-version`） | pyenv 不要．`uv sync` で自動取得 |

### 環境再現コマンド

```powershell
# 1. uv のインストール（初回のみ）
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"

# 2. 依存とランタイムを同期
uv sync
```

## 主要依存ライブラリ (Key Dependencies)

| カテゴリ | パッケージ | 用途 |
| --- | --- | --- |
| シミュレータ | `mitsuba` | 光線追跡コア |
| 数値計算 | `numpy` | 配列計算（評価指標と共用） |
| ジオメトリ | `trimesh` | STL の読み込み・三角形メッシュ操作 |
| シーン定義 | `pydantic` | YAML スキーマのバリデーション |
| 設定ファイル | `pyyaml` | YAML パース |
| 画像 I/O | `pillow` | PNG 出力（実機画像と同形式に揃える） |
| 画像 I/O（RAW） | `rawpy` | DNG（RAW）読み込み．linear raw を保ったまま実測リファレンスを取得（`evaluation/dng_loader.py`） |
| 可視化（2D） | `matplotlib` | 輝度マップ・ヒストグラム・放射状プロファイル等 |
| 画像処理（指標） | `scikit-image` | 構造的類似度 SSIM の算出（形状評価指標，`evaluation/shape_metrics.py`） |
| 可視化（3D） | `pyvista` | 照度ベイク結果のインタラクティブ 3D ビューア（`sm-visualize`） |
| 画像処理（GUI） | `opencv-python` | 実測 PNG での白色板境界選択 GUI（`scripts/select_white_board.py`） |
| 表データ | `pandas` | 均一性指標 CSV の生成・統計集計 |
| テスト | `pytest` | 単体テスト |
| Lint / Format | `ruff` | コードチェック・整形（uv エコシステムと整合） |

※ 具体的なバージョン制約は `pyproject.toml` で固定し，`uv.lock` で再現を保証する．

## ジオメトリ受け渡し (Geometry Pipeline)

Fusion 360 → SmTIAS-LightSim の橋渡し方式：

| 項目 | 採用 | 備考 |
| --- | --- | --- |
| エクスポート形式 | **STL**（バイナリ） | Fusion 360 標準機能で出力可．trimesh で安定して読める |
| 単位 | mm（Fusion 360 デフォルト） | Mitsuba シーンに渡す際は m に換算する（後段で実装） |
| 材料の受け渡し | STL ではメタ情報が落ちるため，**別 YAML / JSON で材料割当を管理** | 例: 「インナー筐体 = 拡散反射 90% / ディフューザー = 透過 60% 散乱角 40°」等 |

OBJ / 3MF も将来検討可．現時点では情報量と Python での扱いやすさのバランスで STL を採用．

## SmTIAS-Evaluation コードの取り扱い (Reuse Policy)

均一性評価コードは **コピーして独立運用**（方針 a）．

- `SmTIAS-Evaluation/src/analysis/uniformity.py`（旧 `src/uniformity.py`）を本リポジトリ内に複製して使う
- 配置先（仮）: `src/sm_tias_lightsim/uniformity.py`
- ファイル冒頭に元の SHA / 出典を docstring で明記
- シミュレータ向けに必要があれば自由に拡張する（例: float64 直接入力の関数追加）

## ディレクトリ構成プレビュー (Directory Layout Preview)

詳細はフェーズ 4（仕様設計）で確定する．現時点の想定:

```
src/sm_tias_lightsim/
  ├── geometry/        # STL 読込・座標変換
  ├── scene/           # Mitsuba シーン構築（光源・材料・センサ）
  ├── render/          # レンダリング実行・画像出力
  ├── uniformity.py    # 評価指標（SmTIAS-Evaluation からコピー）
  └── pipeline.py      # 全体パイプライン CLI
configs/               # シーン・材料・LED 配置の YAML/JSON
output/                # 結果（画像・CSV・図）
tests/                 # pytest
```

## GPU 対応への移行パス (Future GPU Support)

CPU で性能不足になった場合の道筋を残しておく:

1. Mitsuba 3 の variant を `cuda_rgb` または `cuda_spectral` に切替える
2. CUDA Toolkit + 対応 NVIDIA ドライバを Windows に導入（手順書化）
3. シーンコード自体は variant 切替えで動くため，アルゴリズム変更は基本不要

## 参考リンク (References)

- Mitsuba 3 公式: https://www.mitsuba-renderer.org/
- Mitsuba 3 Python tutorial: https://mitsuba.readthedocs.io/en/stable/src/quickstart/python_intro.html
- uv: https://docs.astral.sh/uv/
- trimesh: https://trimesh.org/
