# SmTIAS-LightSim

MiniTIAS（スマートフォン舌画像撮影装置）の照明均一性を実機制作前に検討するための光散乱シミュレーションツール．
LED 配置・ディフューザー形状を仮想的に変えながら，MiniTIAS-Evaluation と同じ指標（CoV／3 ゾーン分析等）で均一性を定量評価できるようにする．

## 開発進捗

現在の進捗: フェーズ 7（実装）— Step 1〜7 完了，Step 8（基準設計キャリブレーション）進行中．
Step 8 進捗: spp 校正（128→1024、ノイズ/物理差を切り分け）→ 反射率スイープ（0.75〜0.92、弱い二次レバーと判明）→ **手法訂正**: シミュ linear と実測 sRGB を直接突合していた交絡を発見．標準 sRGB OETF 順方向適用＋実測 mean アンカーで見かけ差の **約 2/3 が符号化ドメイン不一致**だったと判明．寄与順は OETF（最大）＞ ISP レンズシェーディング（残差主因候補）＞ 反射率（小）．残差 1.6〜1.9 倍は調整せず正直に保持．副次: max_depth=8 は勾配を過大評価（キャリブは depth≥12）．→ **OETF 順方向適用を sm-evaluate へ正規実装完了**（`evaluation/oetf.py` + `EvaluationConfig.oetf`、baseline 有効化・real 非適用、後方互換、参照実装と数値一致テスト済み）．[SPEC_03「キャリブレーション経過」参照](docs/04_SPEC/SPEC_03_基準設計の物理構成.md)．
補足: 内部キャリブ調整は一旦中断し、**シミュ結果の見せ方（3D ビュー）改善**を実施．評価板実レンダ投影 → **path ベイク（`baker.py` mode="path"、多重反射込み per-face、scalar_rgb）** 追加 → 全メッシュ統一着色（共有 lit-clim・log・単一カラーバー）を既定化、`--render` は任意のテクスチャ投影オプション（評価板 E=π·L/ρ で同一スケール）、`--bake-cache` で 1 回計算→以後即時、`--opacity`/`--hide-below`/`--bake-smooth`/`--bake-scale` を追加．さらに **path ベイク max_depth を render 設定から独立（`--bake-max-depth`、既定 16）**＝後段多重反射を積分、**幾何カリング（`--cull-outward` 既定 ON、外向き ≈0 面を非描画）**＝暗殻の濁り/見かけ段差を解消、マーカー個別非表示フラグ、を追加．実装完了．
既知の制約（受容済み）: per-face ベイクはメッシュ境界の継ぎ目・粗メッシュのブロック感・低 samples の MC ノイズ・scalar_rgb の遅さ（高 samples 非現実的）あり．精細な評価は 2D `sm-evaluate` で行う（不変）．隣接内壁の見かけ段差は調査の結果「外向き ≈0 面の混在」が主因と判明＝幾何カリングで解消（内壁照度自体は物理どおりほぼ均一）．
次のアクション（可視化・コミット後の別タスク）: シーム/粒状感の解消には全メッシュ UV 統合＋シームレスライトマップベイク（別プロジェクト規模）．必要時に別途 `/implement`．path ベイク高速化（wavefront/GPU）も別タスク．
補足: **実機搭載 LED の物性確定**（LED Paradise LP-2835D90VW / Ra98 SunLightLED 2835 4000K、Vf 3.1V・If 60mA・Φv 16–19 lm @60mA・配光角 120°・規格通り 60mA 駆動前提）．規格値から独立推定した radiance ≈ 2030 W/(m²·sr) は現状校正値 2807 と 1.38× 差で、反射率 0.85→0.89 への調整で物理範囲内に説明可能．既知差分 #3（LED 実 W 値未検証）クローズ．**形状指標への影響なし**（線形ゲイン）．配光は厳密 Lambertian 仮定継続（詳細 IES 未提供、実 SMD 2835 のやや前方凸性は ISP LSC と打ち消し合う近似として現状妥当）．詳細: [SPEC_03 LED セクション](docs/04_SPEC/SPEC_03_基準設計の物理構成.md#led光源)．
補足: **輝度マップ「形」の追跡を導入**（[TEST_03 輝度マップ形状追跡](docs/06_TEST/TEST_03_輝度マップ形状追跡.md) + `scripts/build_luminance_evolution_panel.py`）．重要な発見: **これまでの全 7 改善ステップ (8-1〜8-7) で輝度マップの「形」は全く変わっていない**．OETF は単調変換で形を変えず，発光面サイズ変更も形を変えない．**実機は中央付近にピークを持つ楕円状，シミュは下端のみ明の Y 軸単調勾配**．**LSC モデル化は「数値残差縮小」と「形の構造的改善」の両方を担う唯一の改善候補**．以後の改善判断は「数値 + 形」の 2 軸で行う．
補足: **Step 8-8 完了**．linear 評価モードに mean 揃え正規化を導入（`evaluation/normalize.py` の `apply_mean_anchor` + `EvaluationConfig.normalization` スキーマ + CLI 統合 + OETF 排他バリデーション）．OETF 露出アンカー（Step 8-3）と同じ思想を linear ドメインに対称展開．`configs/eval_baseline_linear.yaml` で有効化（target_mean=146.7146）．形状指標 (CoV/勾配/C/P/max-min) は厳密不変，mean のみ target_mean に揃う．動作確認: α=0.961934 で baseline luminance.npy が mean=146.7146, CoV=0.182577 で評価可能．テスト 62 件追加（既存 441 + 新規 62 = 503 件全通過）．
補足: **Step 8-9 完了**．LED 18 個の位置を Fusion 360 設計 STL (`configs/meshes/SmTIASv3.stl`) から抽出して `scene_baseline.yaml` を更新．`scripts/extract_led_positions_from_stl.py` で連結成分分割→ LED/カバー識別→ bottom/right/left 自動命名．主な変更: 下基板 LED 配置を「等間隔 8.7mm」→「3+ギャップ+3 (4.2mm+10.8mm+4.2mm)」へ訂正（実機写真の中央電流制限抵抗 2 個と整合）．左右基板も実位置に修正．**形状指標は ~1% 以内のほぼ不変**（多重反射が支配的，LED 数 mm 誤差は ROI 上で平滑化）．絶対 mean は +10% 増加（α 値 0.962→0.873）．既知差分 #2 をクローズ．TEST_03 比較パネルに Step 8-9 を追加（5 枚並列）．
次のアクション（キャリブ再開時）: 残差に **LSC（ISP レンズシェーディング）順方向モデル**を当てる（物理動機づけ低自由度形、overfitting 回避・取得パラメータ数明記）．

実装済みモジュール:
- `src/sm_tias_lightsim/uniformity.py` — Rec.709 輝度変換 + CoV/std/max-min（MiniTias-Evaluation コピー）
- `src/sm_tias_lightsim/evaluation/zones.py` — 正規化楕円距離マップ + 3 ゾーン分類 + ゾーン別統計
- `src/sm_tias_lightsim/evaluation/radial.py` — 20 ビン放射状輝度プロファイル
- `src/sm_tias_lightsim/evaluation/roi.py` — `image_pixel` 型矩形 ROI 抽出（2D/3D 配列対応）
- `src/sm_tias_lightsim/evaluation/oetf.py` — 標準 sRGB OETF（IEC 61966-2-1）+ 露出ソルバ（OETF 後 ROI mean を実測値に対数二分でアンカー）+ 順方向適用．シミュ linear を実測 sRGB ドメインへ変換
- `src/sm_tias_lightsim/evaluation/normalize.py` — linear mean anchor 正規化（`apply_mean_anchor`）．OETF と排他適用，形状指標は厳密不変で mean のみ target_mean に揃う．`configs/eval_baseline_linear.yaml` で有効化
- `src/sm_tias_lightsim/evaluation/visualize.py` — matplotlib 可視化（輝度マップ / ヒストグラム / 放射プロファイル / ゾーンマップ）．MiniTias-Evaluation 互換スタイル（hot cmap，zone_map は luminance 背景 + 境界線）
- `src/sm_tias_lightsim/scene/schema.py` — Pydantic ベース YAML スキーマ + ローダ．SensorConfig は perspective / orthographic 両対応
- `src/sm_tias_lightsim/geometry/loader.py` — STL 読込（trimesh）+ `LoadedMesh` データクラス
- `src/sm_tias_lightsim/geometry/transforms.py` — mm⇄m 単位スケール変換
- `src/sm_tias_lightsim/scene/{lights,materials,sensors}.py` — Mitsuba emitter / BSDF / sensor dict 変換（sensors は orthographic 対応）
- `scripts/select_white_board.py` — 実測 PNG で白色板境界を OpenCV GUI で選択（Step 8 キャリブ用）
- `scripts/visualize_roi_3d.py` — 評価板 STL に ROI を 3D 投影（PyVista，Step 8 キャリブ用）
- `src/sm_tias_lightsim/scene/builder.py` — SceneConfig → Mitsuba scene dict（PLY 一時ファイル経由）
- `src/sm_tias_lightsim/render/runner.py` — variant 管理 + `mi.render` 実行
- `src/sm_tias_lightsim/render/output.py` — PNG / luminance.npy 出力
- `src/sm_tias_lightsim/cli/render.py` — `sm-render` CLI（YAML → PNG / luminance.npy）
- `src/sm_tias_lightsim/cli/evaluate.py` — `sm-evaluate` CLI（PNG / luminance.npy → metrics.csv + figures/）．`oetf.enabled` 時は ROI 抽出後・指標算出前に sRGB OETF を順方向適用，`normalization.enabled` 時は OETF 前段に linear mean 揃え正規化（OETF と排他）．後方互換、シミュ用設定のみ
- `src/sm_tias_lightsim/visualize/baker.py` — face 中心の照度ベイク．`mode="direct"`（shadow ray + cosine + 距離減衰、直接光のみ、後方互換）/ `mode="path"`（scalar_rgb・完全シーン・コサイン重点 hemisphere MC、多重反射込み per-face、`exclude_mesh_ids` 対応）．`max_depth` 引数で path ベイクの反射回数を render 設定から独立設定（None で render 継承＝後方互換）
- `src/sm_tias_lightsim/visualize/projection.py` — orthographic センサ投影の純関数（評価板メッシュ特定 / `project_luminance_to_vertices` 頂点 bilinear 投影 / `compute_orthographic_uv` テクスチャ UV / `compute_face_camera_mask` 幾何 Z ベース巻き順非依存の評価面選択 / `compute_inward_face_mask` 法線がシーン中心側を向く内向き面判定＝幾何カリング用）．`sensors.py` look_at@scale 規約と整合（SPEC_03「画像↔物理の向き」検証済）
- `src/sm_tias_lightsim/visualize/viewer.py` — PyVista 3D ビューア．既定＝全メッシュ統一ベイク着色（**lit のみ共有 clim**・log/linear・単一カラーバー・`bake_opacity` 半透明・`hide_below` 非表示・`bake_smooth` 平滑化・depth peeling・viridis）＋**`cull_outward`（既定 ON）で外向き ≈0 面を非描画**＝暗殻の濁り/見かけ段差を解消・clim も可視内向き面に密着；`hide_sensor_marker`/`hide_led_markers` でマーカー個別非表示；`luminance_map` 指定時＝評価板 512² テクスチャ投影（E=π·L/ρ で壁と同一 W/m² スケール、内側カメラ向き face のみ、外側ニュートラル、マスク無効時 per-vertex フォールバック）
- `src/sm_tias_lightsim/cli/visualize.py` — `sm-visualize` CLI（YAML → 3D 表示 / screenshot）．`--bake-mode {direct,path}` / `--bake-samples` / `--bake-max-depth`（path ベイクの反射回数、既定 16、render 設定から独立）/ `--bake-cache <npz>`（1回計算→以後即時）/ `--cull-outward|--no-cull-outward`（既定 ON）/ `--opacity` / `--hide-below` / `--bake-smooth` / `--bake-scale {linear,log}` / `--clip-percentile` / `--no-sensor-marker`・`--no-led-markers`・`--no-markers` / `--render <luminance.npy>`（任意・テクスチャ投影）．`--render` 無し＝全面統一ベイク（既定）
※ ステップ完了時にここを更新すること．

## 必須ルール（コード実装時）

<!-- プロジェクト立ち上げ後，規約整備フェーズで追加する -->

### Git 運用（GUIDE_04 準拠）

- ブランチ名・コミットメッセージの書式は GUIDE_04 に従う
- コミットは `/commit` を使用する（push・PR 作成は `/commit push`）

### エージェントチーム（GUIDE_05 準拠）

- 実装は `/implement <タスク>` で開始する（コーディング → テスト → リファクタリング → ドキュメント更新）
- Phase 1 後に人間が動作確認，Phase 2 でテスト失敗時のみ方針判断
- Phase 2 成功後は Phase 3 → Phase 4 まで自動で進む（Phase 4 で更新がある場合のみ確認）
- テスト・リファクタリングをスキップしない

### 手動確認が必要な作業（自分で完了させないこと）

以下は実装完了後にユーザーへ報告し，確認・実施を依頼すること．

- 外部サービスの設定（コンソール操作，セキュリティルール変更等）
- 実機・ブラウザでの動作確認
- ストアへのアップロード・リリース作業

## ドキュメント

設計・規約に関する情報は docs/ にある．
コードを書く前に関連するファイルを読むこと．

### 01_GUIDE（規約・ルール）

- プロジェクト立ち上げフロー: docs/01_GUIDE/GUIDE_01_プロジェクト立ち上げフロー.md
- ドキュメント作成規約: docs/01_GUIDE/GUIDE_02_ドキュメント作成ガイド.md
- ファイル命名規則: docs/01_GUIDE/GUIDE_03_ファイル命名規則.md
- Git 運用ルール: docs/01_GUIDE/GUIDE_04_Git運用ルール.md
- エージェント運用ルール: docs/01_GUIDE/GUIDE_05_エージェント運用ルール.md
- コーディング規約: docs/01_GUIDE/GUIDE_06_コーディング規約.md
- テスト方針: docs/01_GUIDE/GUIDE_08_テスト方針.md

### 02_ENV（環境）

- 技術スタック: docs/02_ENV/ENV_01_技術スタック.md
- 環境構築手順: docs/02_ENV/ENV_02_環境構築手順.md
- 管理者用環境構築手順: docs/02_ENV/ENV_03_管理者用環境構築手順.md

### 03_PLAN（計画）

- 要件定義書: docs/03_PLAN/PLAN_01_要件定義書.md
- 開発ステップ: docs/03_PLAN/PLAN_02_開発ステップ.md

### 04_SPEC（仕様・設計）

- アーキテクチャ設計: docs/04_SPEC/SPEC_01_アーキテクチャ設計.md
- シーン定義仕様: docs/04_SPEC/SPEC_02_シーン定義仕様.md（シーン YAML + 評価 YAML のスキーマ）
- 基準設計の物理構成: docs/04_SPEC/SPEC_03_基準設計の物理構成.md（評価関連は SPEC_04 に分離済み）
- 評価仕様: docs/04_SPEC/SPEC_04_評価仕様.md（評価パイプライン・ROI・OETF・メトリクス・可視化・キャリブ目標と経過要約）

### 05_TECH（技術設計）

<!-- 必要に応じて実装フェーズで追加する -->

### 06_TEST（テスト）

- キャリブレーション検証履歴: docs/06_TEST/TEST_01_キャリブレーション検証履歴.md（Step 8 イテレーション 8-1〜8-7 のフル記録．仮説／変更／数値／解釈／学びを時系列で）
- シミュレーション実行記録: docs/06_TEST/TEST_02_シミュレーション実行記録.md（output/ 各サブディレクトリの索引．Step との対応・シーン/評価 config・主要指標・再現コマンド・削除推奨）
- 輝度マップ形状追跡: docs/06_TEST/TEST_03_輝度マップ形状追跡.md（数値とは独立に「形」を実機に近づける観点．比較パネル画像と LSC モデル化の構造的意義）
