Newer
Older
SmTIAS-LightSim / docs / 04_SPEC / SPEC_01_アーキテクチャ設計.md

アーキテクチャ設計 (Architecture)

概要 (Overview)

SmTIAS-LightSim は次の 2 段階を独立した CLI として提供する.

  1. render: シーン定義 YAML + STL メッシュを入力に,Mitsuba 3 で擬似撮影画像(PNG)と輝度マップを出力する.
  2. evaluate: PNG または輝度マップ + ROI 設定を入力に,SmTIAS-Evaluation 互換の均一性指標(CSV)と可視化(PNG)を出力する.

evaluate を独立させることで,実測 PNG(SmTIAS で撮影したもの)にも同じコマンドが使える.シミュレーションと実測を同じ物差しで比較できる.

全体パイプライン (Pipeline)

                         [Fusion 360]
                              ↓ STL export
    ┌─────────────────────────────────────────────────────────────┐
    │  configs/                                                  │
    │   ├── scene_baseline.yaml   (光源・材料・センサ・評価面定義) │
    │   └── meshes/                                              │
    │       └── *.stl                                            │
    └─────────────────────────────────────────────────────────────┘
                              ↓
    ┌─────────────── render ──────────────┐
    │  scene/builder  →  Mitsuba scene    │
    │  render/runner  →  mi.render(...)   │
    │  render/output  →  PNG / luminance  │
    └──────────────────────────────────────┘
                              ↓
                  output/<scene-id>/
                    ├── render.png
                    └── luminance.npy
                              ↓
    ┌─────────────── evaluate ────────────┐
    │  evaluation/roi      →  ROI抽出     │
    │  uniformity.py       →  CoV / std    │
    │  evaluation/zones    →  3ゾーン      │
    │  evaluation/radial   →  放射プロファ  │
    │  evaluation/visualize → 可視化PNG    │
    └──────────────────────────────────────┘
                              ↓
                  output/<scene-id>/
                    ├── metrics.csv
                    └── figures/
                        ├── luminance_map.png
                        ├── histogram.png
                        ├── radial_profile.png
                        └── zone_map.png

モジュール構成 (Modules)

src/sm_tias_lightsim/
├── __init__.py
├── geometry/
│   ├── loader.py        # trimesh で STL 読込・三角形配列取得
│   ├── subdivide.py     # 三角形メッシュ均一分割(最大辺長以下に決定論的に分割)
│   └── transforms.py    # 単位変換 (mm→m)・座標系変換
├── scene/
│   ├── schema.py        # YAML スキーマ定義・バリデーション
│   ├── builder.py       # YAML → Mitsuba scene dict 変換の本体
│   ├── lights.py        # LED 光源 (point / area / spot) のシーン要素生成
│   ├── materials.py     # BSDF(拡散・誘電体・薄膜散乱等)の生成
│   ├── sensors.py       # カメラセンサ (perspective / orthographic) の生成
│   └── paths.py         # YAML からの相対メッシュパス(スイープ生成スクリプト用)
├── render/
│   ├── runner.py        # mi.set_variant(ensure_variant)+ mi.render の実行
│   ├── output.py        # HDR film → PNG / luminance.npy 出力
│   └── pipeline.py      # YAML → レンダ → 保存の一括処理(render_yaml.CLI とスイープの共通本体)
├── runtime/
│   ├── llvm_init.py     # LLVM JIT 初期化(DRJIT_LIBLLVM_PATH 自動探索・variant 経路ログ)
│   └── overrides.py     # 環境変数による実行時上書き(SM_RENDER_VARIANT / SM_DRJIT_THREADS)
├── remote/
│   ├── commands.py      # サーバで実行するシェルコマンドの組み立て(純関数)
│   ├── files.py         # push の送信ファイル選定・除外規則・prune 対象の算出
│   └── transfer.py      # tar over ssh の送受信(pull 展開の安全検査)
├── uniformity.py        # SmTIAS-Evaluation からコピー(Rec.709, CoV, max/min)
├── evaluation/
│   ├── roi.py           # 画像 ROI 抽出(image_pixel 型)
│   ├── zones.py         # 3 ゾーン分析(center / middle / periphery)
│   ├── radial.py        # 放射状プロファイル + 動径 min/max 比
│   ├── oetf.py          # sRGB OETF 順方向適用 + 露出アンカー(シミュ用)
│   ├── normalize.py     # linear mean anchor 正規化(OETF と排他)
│   ├── dng_loader.py    # DNG(RAW)読込(linear raw 取得,実測リファレンス用)
│   ├── shape_metrics.py # 形状指標(輝度重心 / 角度-放射分解 / PCA / SSIM / NCC)
│   ├── visualize.py     # matplotlib による可視化 PNG 出力
│   └── pipeline.py      # 画像 + 評価 YAML → 指標 dict + metrics.csv(+ figures/)の一括処理(evaluate_image)
├── visualize/
│   ├── baker.py         # 各 face 中心の照度ベイク(direct / path モード)
│   ├── projection.py    # orthographic センサ投影の純関数(評価板への輝度投影)
│   └── viewer.py        # PyVista による 3D インタラクティブビューア
└── cli/
    ├── render.py        # `sm-render` エントリポイント
    ├── evaluate.py      # `sm-evaluate` エントリポイント
    ├── visualize.py     # `sm-visualize` エントリポイント
    └── remote.py        # `sm-remote` エントリポイント(研究室サーバでの実行)

各層の責務 (Module Responsibilities)

層責務主要な型・出入力
geometrySTL を読み,Mitsuba が扱える単位・座標系に揃える.メッシュの妥当性チェック入力: STL ファイルパス.出力: 頂点・面配列 + 単位情報
scene/builderYAML 設定全体を Mitsuba scene dict に変換するエントリ.他のサブ層を呼ぶ入力: YAML dict.出力: Mitsuba scene
scene/lightsYAML 光源定義 → Mitsuba の point / area / etc. emitter1 LED 定義 → 1 emitter
scene/materialsYAML 材料定義 → Mitsuba BSDF(diffuse / dielectric / thindielectric)1 材料定義 → 1 BSDF
scene/sensorsYAML センサ定義 → Mitsuba perspective / orthographic センサ1 センサ定義 → 1 sensor.orthographic は照度マップ取得用
geometry/subdivide三角形メッシュ → 最大辺長以下に均一分割した三角形メッシュ決定論的(同一入力→同一出力).ベイクの空間解像度を均一化
render/runnerMitsuba scene + パラメータ → 輝度配列spp / max_depth / variant 切替
render/output輝度配列 → PNG / luminance.npy ファイルtone mapping 等の選択肢を持つ
render/pipelineシーン YAML + 出力先 → render.png / luminance.npyvariant 解決(引数 > 環境変数 > YAML)込み.スイープからプロセス内で直接呼べる
runtime/llvm_initLLVM JIT 環境初期化DRJIT_LIBLLVM_PATH 自動探索(Windows / Ubuntu・Debian の libLLVM-<版>.so / Fedora 形式)+ variant 経路の INFO/WARNING ログ
runtime/overrides環境変数による実行時上書きの解決と適用SM_RENDER_VARIANT(variant.sm-render --variant が優先)/ SM_DRJIT_THREADS(Dr.Jit スレッド数上限.不正値は ValueError)
scene/pathsメッシュの絶対パス → YAML からの相対パス(POSIX 区切り)手元とサーバで同じ YAML を読めるようにする.別ドライブで相対化できないときは警告して絶対パス
remote/commands設定 → サーバで実行するシェルコマンド文字列純関数.クォート・ジョブ名/GPU の検証・終了コード 90〜93
remote/files手元の作業ツリー → 送信ファイル一覧 / prune 対象除外規則.output/ は送らず,prune は src/ tests/ scripts/ のみ
remote/transferファイル一覧 ⇄ tar ストリームpull 展開は要求パス外・不正な名前・リンクを拒否(パストラバーサル対策)
evaluation/roi画像 + ROI 定義 → ROI 内の輝度配列image_pixel 型(scene_face は将来実装)
uniformity輝度配列 → 均一性指標 dictSmTIAS-Evaluation 仕様準拠
evaluation/zones輝度配列 → 中心 / 中間 / 周辺の各統計距離正規化を内部で行う
evaluation/radial輝度配列 → 中心からの距離 vs 平均輝度 + 動径 min/max 比プロット用データ
evaluation/oetfシミュ linear 輝度 → sRGB 符号化値(露出アンカー)シミュのみに適用.実測 PNG には適用しない
evaluation/normalizelinear 輝度 → mean を target_mean に揃えた輝度線形ゲイン.形状指標は不変.OETF と排他
evaluation/dng_loaderDNG(RAW)→ linear raw 配列実測リファレンスの linear 取得
evaluation/shape_metrics輝度配列(+ 任意の参照画像)→ 形状指標輝度重心 / 角度-放射分解 / PCA / SSIM / NCC
evaluation/visualize各種統計 → matplotlib 図 PNG可視化のみ.データ加工はしない
evaluation/pipeline画像 + 評価 YAML + 出力先 → 指標 dict(metrics.csv を書く)save_figures=False で図を省略.段階別の EvaluationStepError を投げる
visualize/bakerシーン + 光源 → 各 mesh face 中心の照度(W/m²)direct(直接光)/ path(多重反射込み)モード
visualize/projectionorthographic センサ + 評価板メッシュ → 頂点 / テクスチャ投影純関数.画像 ↔ 物理の向き整合
visualize/viewerシーン + 照度 → PyVista インタラクティブ 3D ウィンドウメッシュ着色 / 光源マーカー / センサ視線 / スライド表示スタイル
cli/render, cli/evaluate, cli/visualize各ステップの CLI ラッパー引数パースと例外 → 「エラー: …」+ 終了コード 1 の変換だけ.本体は render/pipeline・evaluation/pipeline
cli/remote研究室サーバでの実行(push / run / status / logs / attach / kill / pull)ssh の起動・サーバ上での実行検出.使い方は ENV_04「研究室サーバでの実行」

エントリポイント (CLI Entry Points)

pyproject.toml の [project.scripts] に登録する:

[project.scripts]
sm-render = "sm_tias_lightsim.cli.render:main"
sm-evaluate = "sm_tias_lightsim.cli.evaluate:main"
sm-visualize = "sm_tias_lightsim.cli.visualize:main"
sm-remote = "sm_tias_lightsim.cli.remote:main"

使い方:

# シミュ実行
uv run sm-render --scene configs/scene_baseline.yaml --output output/baseline/

# 評価(シミュ画像)
uv run sm-evaluate --image output/baseline/render.png --config configs/eval_default.yaml --output output/baseline/

# 評価(実測画像)
uv run sm-evaluate --image data/whiteboard_real.png --config configs/eval_default.yaml --output output/real/

# 3D 照度ビューア(キャリブレーション中の調査ツール)
uv run sm-visualize --scene configs/scene_baseline.yaml                       # インタラクティブウィンドウを開く
uv run sm-visualize --scene configs/scene_baseline.yaml --screenshot vis.png  # PNG 保存のみ

# 研究室サーバ(既定 Newton)で回す.手元から送って tmux で実行し,結果を持ち帰る
uv run sm-remote push
uv run sm-remote run --name baseline --gpu 0 -- sm-render --scene configs/scene_baseline.yaml --output output/baseline/
uv run sm-remote pull baseline

sm-render --variant cuda_ad_rgb(または環境変数 SM_RENDER_VARIANT)で YAML の render.variant を上書きできる.sm-remote run は既定で cuda_ad_rgb を渡す.詳細は ENV_04「研究室サーバでの実行」を参照.

sm-visualize は上記の他に,ベイク方式(--bake-mode direct|path)・平滑化(--bake-smooth / --bake-smooth-radius / --bake-denoise)・三角形分割(--bake-subdivide)・キャッシュ(--bake-cache)・発表スライド向け表示(--style slide / --cmap)・マーカー非表示(--no-markers 等)など多数のオプションを持つ.全フラグは uv run sm-visualize --help を参照.

ディレクトリ構成(プロジェクトルート)

SmTIAS-LightSim/
├── src/sm_tias_lightsim/   # 上述
├── configs/
│   ├── scene_baseline.yaml
│   ├── eval_default.yaml
│   └── meshes/             # STL ファイル群
├── output/                 # シミュ・評価結果(.gitignore 対象)
├── tests/
│   ├── test_geometry.py
│   ├── test_scene_builder.py
│   ├── test_uniformity.py
│   └── fixtures/
└── docs/

キャリブレーション戦略 (Calibration)

実測値(CoV ≈ 0.0426,勾配 ≈ 6%)との一致を確認するための運用:

  1. 現行 SmTIAS の構成を scene_baseline.yaml に再現
  2. sm-render → sm-evaluate で指標を算出
  3. 実測値と比較し,差分が大きい場合は次の順で疑う:
    • ① 光源の配光(Lambertian / cosine 分布の前提が妥当か)
    • ② 材料パラメータ(拡散反射率・透過散乱)
    • ③ ジオメトリの単位・座標
    • ④ サンプル数(spp)が不足していないか
  4. 一致した時点でキャリブレーション完了.以降の改良案はこのベースラインからの相対比較で評価

許容範囲の数値は基準設計のレンダリング結果を見て確定する(PLAN_02_開発ステップ.md 内で定義).

既知の前提 (Assumptions)

  • 入力 STL は閉じたメッシュ(モンテカルロ光線が漏れない)であること
  • 単位は YAML 側で明示する(unit: mm).Fusion 360 の既定 mm 出力を想定
  • LED の配光は当初 Lambertian で仮置きし,必要に応じて IES データに置換可能な構造にしておく
  • 色再現性は将来課題(要件定義書のスコープ外)