以下は 2026-06-25 のテンプレート同期(進捗ログ 2 段構成への移行)に伴い,CLAUDE.md「開発進捗」セクションに蓄積していた
補足:ログを移行したもの.移行時点の文面をそのまま保持している(古い記述・関数名等も歴史的記録として保持.今後の新規エントリは GUIDE_05 の書式に従い,git logで取れる詳細は書かない).
現在の進捗(移行時点): フェーズ 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「キャリブレーション経過」参照.
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 面を非描画)**=暗殻の濁り/見かけ段差を解消、マーカー個別非表示フラグ、を追加.実装完了.
sm-evaluate で行う(不変).隣接内壁の見かけ段差は調査の結果「外向き ≈0 面の混在」が主因と判明=幾何カリングで解消(内壁照度自体は物理どおりほぼ均一)./implement.path ベイク高速化(wavefront/GPU)も別タスク.scripts/build_luminance_evolution_panel.py).重要な発見: これまでの全 7 改善ステップ (8-1〜8-7) で輝度マップの「形」は全く変わっていない.OETF は単調変換で形を変えず,発光面サイズ変更も形を変えない.実機は中央付近にピークを持つ楕円状,シミュは下端のみ明の Y 軸単調勾配.LSC モデル化は「数値残差縮小」と「形の構造的改善」の両方を担う唯一の改善候補.以後の改善判断は「数値 + 形」の 2 軸で行う.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 で評価可能.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 枚並列).LED基板カバー.stl 1 枚のみだったが,scripts/extract_led_positions_from_stl.py --export-covers configs/meshes/ で SmTIASv3.stl から LED基板カバー下/右/左.stl の 3 ファイルを書き出し,scene_baseline.yaml の geometry を led_cover_bottom/right/left の 3 メッシュエントリに展開.右・左基板の LED が「カバーなしで浮く」状態を解消.多重反射計算への影響は軽微だが物理的に正確.spot emitter (cutoff=90°/beam=30°,FWHM 120° 一致,flux 保存 I_0=0.026784 W/sr) で表現する試行.SpotLight クラスを schema.py に追加,lights.py に spot 分岐実装,configs/scene_baseline_spot.yaml を並列保持.目視で X 方向の対称性が部分改善(下端の明るい領域が中央寄りに集中)だが,数値指標は微悪化(CoV +4%, 勾配 +15%).LED 指向性は形の一部(X 方向)を変えるが,Y 方向の中央ピークは LSC モデル化(Step 8-N)が必要.本格採用は LSC との組み合わせ評価後に判断.付随発見: spot で mean が 14.6× 暗くなる(理由は spot falloff 関数の cos vs 角度ドメイン smoothstep の解釈差等を仮説).configs/scene_baseline_datasheet.yaml に並列保持.spot を cos^1.2 相当の前方凸 (cutoff=85°/beam=26.72°,FWHM 111.72°) に詳細化 + 反射率を Step 8-6 で導出した物理整合点 0.89 に変更 + I_0 を規格値 Φv=17.5 lm から導出 (I_0=0.021951 W/sr).形は依然 Y 軸単調勾配で Step 8-10 と Step 8-9 の中間値.データシート従順度を上げても形は実機に近づかないことを確定.副次的に「規格値だけで mean を実機に合わせることはできず,校正値には他のレバーの累積吸収が含まれる」が再確認された.本筋 LSC モデル化が依然必要.schema.py の RenderConfig に ptracer integrator を追加,configs/scene_baseline_perspective_{path,ptracer}.yaml で perspective sensor + scalar_rgb + spp=4096 で比較.bot/top 比が path 2.035 vs ptracer 2.006 で誤差 1.4% で一致=形は方向独立.絶対値は Mitsuba 実装の正規化差で 1.99× 違うが形(空間パターン)は同じ.副次的発見: orthographic + ptracer は Mitsuba 3 では実行不能(Endpoint::sample_direction() 未実装).これにより「方向変更で形を実機に近づける道は無い」が確定し,LSC モデル化が唯一の道である結論が強化された.
configs/scene_baseline.yaml,3 回中央値): B1 sm-render = 507.86 s(≈8.46 分)/ B2 sm-visualize path bake (samples=16) = 55.97 s.副次発見: DRJIT_LIBLLVM_PATH 環境変数の消失で sm-render が ImportError でクラッシュしていたことを発見.C:\Program Files\LLVM\bin\LLVM-C.dll を発見し User scope に永続化して復旧.sm-visualize の direct bake は内部 scalar_rgb 固定のため過去ログでも警告は出ていたが完走していた.方向修正: Speed-1 当初の「JIT 有効化で高速化」は既に JIT 経路に乗っているため不成立 → 「LLVM-C.dll 自動検出と診断ログ」に再定義(再発防止).本命の高速化レバーは Speed-2 path bake wavefront 化(10× 以上見込み).GPU は Intel HD Graphics 520 のみで CUDA 不可,CPU 側完結方針.精度(spp/max_depth)は不変.src/sm_tias_lightsim/runtime/llvm_init.py に ensure_drjit_libllvm_path()(標準パス自動探索→ os.environ 設定)と log_variant_status()(llvm_/cuda_/scalar_ 経路を INFO 明示,要求 llvm_* で実 scalar_* なら WARNING 追加)を新規実装.render/runner.py で variant=llvm_* 時に自動検出を呼び、ImportError 時は原因明示ログ→ re-raise.visualize/baker.py でも log_variant_status 呼び出し追加+ Speed-2 wavefront 化用に LLVM 自動探索の分岐を先取り.cli/render.py で import 順を制御.docs/02_ENV/ENV_02_環境構築手順.md に LLVM インストール手順・DRJIT_LIBLLVM_PATH 説明・動作確認コマンドを追記.速度は不変(コード経路同等).数値同等性: SHA256 は MC 内部シードで異なるが平均相対誤差 7.23e-05 で統計同等性パス.これで「環境変数が消えて沈黙クラッシュ」する事故が再発しない土台が整備された.MiniTIAS_20260408_144434 もこのモードで取得されており,シミュ側でいくらモデルを精緻化しても比較対象が不安定.当初考えていた「LSC モデル化」より上位の問題として「定量撮影モード」を MiniTIAS 側に追加することを優先する.Android Camera2 API には STATISTICS_LENS_SHADING_CORRECTION_MAP・SHADING_MODE=OFF・MANUAL_SENSOR/MANUAL_POST_PROCESSING 能力フラグが存在し,これらを活用すれば「ISP 介入を最小化した再現性ある撮影」が可能.要求仕様を TECH_01 に,ハンドオフ手順を TECH_02 に新規作成.データ受け渡しは reference_measurement/quantitative/ 配下(gitignore 対象).SmTIAS-LightSim 側のキャリブ作業は本仕様書を MiniTIAS に渡した時点で一旦停止.LEVEL_3(最上位)でハードウェア能力フル.Phase 1〜5 全完了で DNG (RAW_SENSOR) 経路を第 1 優先採用.撮影設定: 1/60s + ISO 40 + AWB/NR/EDGE/AF/AE OFF + TONEMAP 線形 + BLACK_LEVEL_LOCK + SHADING_MODE=HIGH_QUALITY (★) + STATISTICS_LENS_SHADING_MAP_MODE=ON.LSC マップは 13×17.保存ファイルは MiniTIAS_QM_*.{dng, meta.json, preview.jpg} 3 種.SHADING_MODE 判断: HIGH_QUALITY を本流維持(Mitsuba orthographic 出力 ≒「ISP が完璧に補正できた場合の理想値」で HIGH_QUALITY DNG と直接比較が物理整合).OFF 切替は将来のフォールバック条件 C1-C3 発動時のみ.データ転送は adb pull 推奨.既存実機 PNG の Y' 抽出は BT.601 係数(Rec.709 ではない)も判明.uniformity.py を MiniTias-Evaluation から SmTIAS-LightSim にコピー)を踏襲する役割分担を採用:MiniTias-Evaluation 側で正規実装 → SmTIAS-LightSim 側にコピー.TECH_05 に要求書を作成.既存 PNG 経路と並列対応(後方互換).依存追加: rawpy>=0.21.0.apply_lsc_inverse は誤り(DNG は LSC 未補正で逆ではなく順方向適用が正しい.TECH_05 §4 を訂正済).(2) 過去 Step 8 キャリブの残差 2.1× はドメイン不一致:正しい linear 比較では DNG linear+LSC 0.0689 vs シミュ linear 0.183 = 真の残差 2.66×.(3) 新実機ターゲット = MiniTIAS_QM_20260601_124500(暗闇撮影): CoV=0.0695, 勾配=8.35%, 中心/周辺=1.0911, 動径 min/max=0.860.Step 8-13 以降の正規 baseline.(4) 外乱光ロバスト確認: 室内灯 ON/OFF で指標差 < 1%.SmTIAS 自前照明が支配的で外乱光モデル化不要.(5) 新指標 calc_radial_min_max_ratio を追加.src/sm_tias_lightsim/evaluation/dng_loader.py を handoff_smtias_lightsim/src/dng_loader.py の完全コピーで新規作成.radial.py に calc_radial_min_max_ratio をマージ追加 (nan ビン除外を移植時に補強).pyproject.toml に rawpy>=0.21.0 追加 (実 rawpy==0.27.0).検証 V4 が完全一致: 実 DNG を読み込んで LSC 順方向適用 + 白板 ROI で評価指標 6 件が相対誤差 < 1e-6 で期待値完全一致,空間指標 3 件も絶対誤差 < 0.003.Refactorer 判断: dng_loader.py 内部の _apply_srgb_oetf は既存 oetf.py:apply_srgb_oetf と実装重複だが「コピー方針優先」「用途が異なる」「違反基準未満」でそのまま放置.MetricsConfig.radial_min_max をスキーマ追加,cli/evaluate.py で _run_radial_min_max を追加して metrics.csv に 4 列追加,コンソールサマリに 2 行追加.radial_profile を再利用(重複算出回避).後方互換維持.SPEC_04 §動径 min/max 比 を追記.configs/eval_baseline_dng_target.yaml を新規作成(eval_baseline_linear.yaml ベース,target_mean=207.82,radial_min_max=true,OETF なし).Step 8-13 数値: シミュ CoV=0.1826, 勾配=24.65%, 中心/周辺=1.3271, 動径 min/max=0.6151.実機 DNG+LSC (CoV=0.0695, 勾配=8.35%, C/P=1.0911, 動径 min/max=0.860) と比較して 残差 2.63×(TECH_06 予想「真の残差 2.66×」とほぼ一致).過去 Step 8-3 の「2.1×」は PNG sRGB ガンマ圧縮による楽観値.LSC 取り扱いの結論を TECH_07 に一元化: 3 プロジェクト役割分担 (MiniTias=HIGH_QUALITY 撮影 / MiniTias-Evaluation=lscMap 順方向適用 / SmTIAS-LightSim=一切扱わない),シミュ側で LSC を扱わない物理的根拠 (Mitsuba orthographic = LSC 完璧補正後相当),代替案 3 つ全却下,フォールバック条件 C1-C3,残差解釈 を明文化.handoff_smtias_lightsim/ は整理: 参考スクリプト run_uniformity_dng.py のみ reference_measurement/quantitative/reference_scripts/ に移動,他は取り込み済みのため削除.output/_slide_panels/roi_alignment_check.png でも視覚確認.残差 2.63× の主因は ROI 整合ではないことが確定.副次発見: 評価板は実機画像中央から下方向に約 4.2 mm (65 px) オフセット配置だが ROI もそのオフセットに沿って選択されているため物理領域として整合.BlendBSDFConfig + RoughConductorBSDFConfig,MaterialConfig Union 拡張,forward reference + model_rebuild()) と materials.py 再帰変換 (_build_bsdf_dict) を新規実装.テンプレ configs/scene_baseline_blend.yaml + scripts/sweep_blend_bsdf.py + scripts/build_blend_bsdf_panel.py.weight ∈ {0.05, 0.15, 0.30} × α ∈ {0.1, 0.3, 0.6} の 9 ジョブ実走 (75.5 分).結果: ベースライン純 diffuse (CoV=0.1826) と比較して 全 9 パターンが悪化または不変.実機 (CoV=0.0695) 方向と 逆方向に動く.「形」は w=0.30 で下端中央に specular 集中スポット顕在化.物理的解釈: 純 Lambertian は cos 重み散乱で多重反射の均一化作用が最大.specular 成分は光を集中させ均一化を阻害.3D プリンタ白フィラメントは完全 Lambertian として扱うのが実機挙動に近い近似と判明.A1 は残差 2.63× の主因ではないことが確定.副次成果: スキーマ層に blendbsdf + roughconductor のサポートが入り再利用可能.scripts/sanity_led_groups.py で各基板の 6 LED だけを ON にした一時 YAML を生成 → 3 ジョブ sm-render (約 25 分) → 比較パネル.結果: 方向性 ✓ (bottom は下端中央/right は右側面寄り/left は左側面寄り),左右対称性 ✓ (right mean=47.10 vs left mean=47.08),量的バランスは bottom が right/left の 2.10× で強い.物理的説明: bottom LED は評価板下端真下に X 中央寄り集中で直接光が広範囲 / right/left LED は側面外側 Y 中央付近に分散で中央は多重反射経由.線形性検証は別途未実施(既存 output/baseline/luminance.npy が Step 8-1 時点の古いもの.Mitsuba は理論線形なので baseline 再生成で一致見込み).副次発見: 実機の right/left は 完全な左右対称設計ではない(Fusion STL 実位置と整合).TEST_07 参照.scripts/sweep_led_distribution.py で spot emitter の cutoff_angle を {30°, 60°, 90°, 120°, 150°} で 5 値スイープ (beam_width = cutoff/3,max_depth=16,約 85 分).重要な 2 つの発見: ① 「area light → spot」のステップが本質的 — area (Lambertian) の angular_ratio=0.4536 → spot (どの cutoff でも) 0.34〜0.36 へ 25% 大幅低下 (実機方向).② cutoff スイープ内 (30°→150°) では effect 限定的 — angular_ratio は +0.018 のみ.A8 と真逆のパターン: 数値悪化 (CoV +3〜11%) するが形改善 (angular_ratio -25%).「数値の偽物の一致」(A8) と対をなす「形改善の本物の候補」初実証.物理的解釈: spot は +Z 方向にしか光を出さない → 内壁に当たる成分減・直接光増 → LED 直下の明点 → 半径方向ばらつき支配 (angular_ratio 減).area は半球全方向拡散で多重反射 ambient 支配 → Y 軸勾配.副次発見: 数値最良点 (cutoff=90°) と形最良点 (cutoff=30°) が異なる→キャリブの優先順位議論を明確化.TECH_10 優先順位を再更新: A2/A3/ξ を「形改善候補」へ昇格.scripts/sweep_reflectance.py で d=16 新基準のもと R ∈ {0.75, 0.80, 0.85, 0.89, 0.92} を 5 値スイープ.新指標 (shape_metrics) を初めて感度分析に投入.結果: 既存 4 指標 (CoV/勾配/C/P/動径 min/max) は単調改善 (R=0.75→0.92 で CoV 0.186→0.142 で残差 24% 縮小) するが,新指標 angular_ratio は 0.408→0.494 で実機方向と逆に増加.実機は中央ピーク楕円 (同心円的) なので 形は実機から遠ざかる.物理的解釈: R 上昇で ambient 増 → 半径方向の偏りは圧縮されるが角度方向ばらつきは相対的に圧縮されにくい → angular_ratio 増加.形改善の本筋は B1 筐体幾何精度に最終確定(A1/A8/A9 すべてクリア済で構造的再配分系のみ残る).副次発見: R=0.85 の CoV=0.1604 が max_depth スイープ d=16 と完全一致.新指標を導入していなければ気づけない発見で,形状指標見直し (TECH_11) の正当性が定量データで裏付けられた.scripts/sweep_max_depth.py 約 85 分 + scripts/build_max_depth_panel.py).結果: 全 4 形状指標が 単調に実機方向に改善 (d=8→28 で CoV 0.1817→0.1583 で残差 20.9% 縮小).mean は 207.82 で固定.実用的な収束は d=16 で達成 (d=16→28 で CoV 1.3% のみ).「形」は完全に不変 (Y 軸単調勾配のまま contrast が緩むだけ).物理的解釈: 多重反射は 空間的に均一な ambient 成分で,足しても暗/明の絶対差は縮むが空間配置は不変.「LED が下にしかない」配置の非対称性は除去不能.ユーザー仮説の評価: 方向性は正しい (21-28% 残差縮小) だが実用収束は d=16,実機 (CoV=0.0695) には届かず残差は形改善で詰める必要.新キャリブベースライン: d=16.src/sm_tias_lightsim/evaluation/shape_metrics.py (新規): calc_intensity_centroid / calc_angular_radial_decomposition (angular_ratio: 0=同心円, 1=方向依存) / calc_ssim (scikit-image 依存) / calc_ncc / calc_intensity_pca の純関数 5 つ.MetricsConfig に shape_metrics / shape_reference を追加(後方互換).configs/eval_baseline_dng_target_shape.yaml を新規作成.pyproject.toml に scikit-image>=0.21.0 を追加.TECH_11 で背景・計算式・予想値・遡及的注記を記録.今後の評価方針: 数値指標 4 + 形指標 5 + 視覚比較の 3 軸評価で「数値改善のみで形が変わらない候補」と「形を変えうる候補」を明確に区別する.lightsim/,SmTIAS-Evaluation 引き渡し,各灯単独点灯の白板 ROI 輝度マップ)とシミュ単灯を灯ごとに突き合わせた結果,scene/lights.py の _build_area_light_transform に座標軸取り違えバグを発見.Mitsuba の rectangle は実体「XY 平面・法線 +Z」(実機 Mitsuba で検証)なのに,コードは旧コメント「XZ 平面・+Y 前面」を前提に scale([sw/2, 1.0, sh/2]) と書かれ,高さ sh を潰れた奥行き Z に入れ・縦 Y を無補正(±1m)のままにしていた → 全 18 LED が「幅 ~3mm × 高さ 2000mm」の縦長ストリップ化.全灯が同一 look_at(direction=(0,0,-1), up=(0,1,0))のため local Y→world Y で全灯が world Y に 2m 伸び,板中央の真裏にある下灯だけが過剰に効いて 2.1× を生んでいた(左右灯は x=±66 で板外・壁脇のため損失大).修正は 1 行: scale([sw/2, sh/2, 1.0]).
output/{sanity_fix_1024,baseline_fix_1024}/,比較図 output/_slide_panels/{sim_vs_real_shape_fixed,sim_vs_real_colormap_fixed}.png,記録 TEST_08.lightsim/ は実測入力として .gitignore 対象.output/depth_bottom/d{N}/,図 output/_slide_panels/depth_bottom_shape.png.output/refl_bottom/run_r{90,95,98}/,図 output/_slide_panels/refl_bottom_shape.png.rectangle を生成し Mitsuba の bbox() が X=2.80mm / Y=2000.00mm(面積 5600mm²=実物の約 570 倍)と報告,③ builder→_build_area_light_transform→mi.render の呼び出し経路で実レンダ使用を確認.新規ツール scripts/show_led_geometry.py(LED を実サイズ長方形+発光方向矢印で 3D 表示,--buggy で修正前の 2m ストリップ再現,--screenshot で 4 アングル保存)を追加.これで LED 位置・サイズ・向きは実機どおり(評価板を背にする設計で正しい)=形不一致の容疑者から無罪を 3D で確認.
output/_slide_panels/before_after_{shape,amplitude}.png): mean 正規化した「形」は修正前後でほぼ不変(合成 peak/mean 1.54→1.54).バグが壊していたのは形でなく灯間の明るさ(下灯 left基準で 2.10→0.97 へ均等化).だから合成 CoV も小改善にとどまった.