SmTIAS-LightSim は次の 2 段階を独立した CLI として提供する.
evaluate を独立させることで,実測 PNG(SmTIAS で撮影したもの)にも同じコマンドが使える.シミュレーションと実測を同じ物差しで比較できる.
[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
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` エントリポイント(研究室サーバでの実行)
| 層 | 責務 | 主要な型・出入力 |
|---|---|---|
geometry | STL を読み,Mitsuba が扱える単位・座標系に揃える.メッシュの妥当性チェック | 入力: STL ファイルパス.出力: 頂点・面配列 + 単位情報 |
scene/builder | YAML 設定全体を Mitsuba scene dict に変換するエントリ.他のサブ層を呼ぶ | 入力: YAML dict.出力: Mitsuba scene |
scene/lights | YAML 光源定義 → Mitsuba の point / area / etc. emitter | 1 LED 定義 → 1 emitter |
scene/materials | YAML 材料定義 → Mitsuba BSDF(diffuse / dielectric / thindielectric) | 1 材料定義 → 1 BSDF |
scene/sensors | YAML センサ定義 → Mitsuba perspective / orthographic センサ | 1 センサ定義 → 1 sensor.orthographic は照度マップ取得用 |
geometry/subdivide | 三角形メッシュ → 最大辺長以下に均一分割した三角形メッシュ | 決定論的(同一入力→同一出力).ベイクの空間解像度を均一化 |
render/runner | Mitsuba scene + パラメータ → 輝度配列 | spp / max_depth / variant 切替 |
render/output | 輝度配列 → PNG / luminance.npy ファイル | tone mapping 等の選択肢を持つ |
render/pipeline | シーン YAML + 出力先 → render.png / luminance.npy | variant 解決(引数 > 環境変数 > YAML)込み.スイープからプロセス内で直接呼べる |
runtime/llvm_init | LLVM 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 | 輝度配列 → 均一性指標 dict | SmTIAS-Evaluation 仕様準拠 |
evaluation/zones | 輝度配列 → 中心 / 中間 / 周辺の各統計 | 距離正規化を内部で行う |
evaluation/radial | 輝度配列 → 中心からの距離 vs 平均輝度 + 動径 min/max 比 | プロット用データ |
evaluation/oetf | シミュ linear 輝度 → sRGB 符号化値(露出アンカー) | シミュのみに適用.実測 PNG には適用しない |
evaluation/normalize | linear 輝度 → mean を target_mean に揃えた輝度 | 線形ゲイン.形状指標は不変.OETF と排他 |
evaluation/dng_loader | DNG(RAW)→ linear raw 配列 | 実測リファレンスの linear 取得 |
evaluation/shape_metrics | 輝度配列(+ 任意の参照画像)→ 形状指標 | 輝度重心 / 角度-放射分解 / PCA / SSIM / NCC |
evaluation/fullimage | 輝度配列 → 画像全体のノイズ補正付き min/max 比 | 方位に依らない.σ 平滑化 + ノイズ場の極値で補正.純関数 |
evaluation/visualize | 各種統計 → matplotlib 図 PNG | 可視化のみ.データ加工はしない |
evaluation/pipeline | 画像 + 評価 YAML + 出力先 → 指標 dict(metrics.csv を書く) | save_figures=False で図を省略.段階別の EvaluationStepError を投げる |
visualize/baker | シーン + 光源 → 各 mesh face 中心の照度(W/m²) | direct(直接光)/ path(多重反射込み)モード |
visualize/projection | orthographic センサ + 評価板メッシュ → 頂点 / テクスチャ投影 | 純関数.画像 ↔ 物理の向き整合 |
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「研究室サーバでの実行」 |
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/
実測値(CoV ≈ 0.0426,勾配 ≈ 6%)との一致を確認するための運用:
scene_baseline.yaml に再現sm-render → sm-evaluate で指標を算出許容範囲の数値は基準設計のレンダリング結果を見て確定する(PLAN_02_開発ステップ.md 内で定義).
unit: mm).Fusion 360 の既定 mm 出力を想定