Fullseye 設計判断集(ソース中の ★ コメントから生成)
日本語 · English · 简体中文 · 繁體中文 · 한국어 · Deutsch
この repo は、なぜそうなっているかをソースのコメントに書いている。そのうち ★ を付けたものが「効く知見」—— 測って分かったこと、踏んだ失敗、そう作った理由。ここはそれを機械的に集めた生成物で、正本はソースの側にある(だから食い違わない)。
accel_match.py
- L170 — ★窓はテンプレより大きくないと full-overlap 位置がゼロになる → r = T//2 + f(粗誤差) + win。
acoustics.py
- L1173 — ★
med == 0 を一律 inf にしていた —— peak も 0 のとき(無音・帯域に 何も無い)まで「無限に卓越したピーク」と報告していた。この 2 つの数は docstring のとおり「何も無くてもピーク周波数を返してしまう」ことへの 正直さの指標なのに、いちばん嘘になる向きに振れていた。0/0 は 0.0 が答え。 (2026-09-05: Linux / numpy 2.5.2 で表面化。旧版はフィルタの残差が わずかに残って med > 0 になっていただけで、不具合は前からあった。)
- L1181 — ★ 大域中央値は帯域を狭めると順序が逆転する(純雑音 11375 対 本物の欠陥 9433。2026-09-06 実測、_local_prominence の表を見よ)。 帯域幅に依らない判定にはこちらを使う。既存の 2 つは意味を変えずに残す —— 名前が同じで中身が変わるほうが、増えるより危ない。
- L1789 — ★
med == 0 を一律 inf にしていた —— peak も 0 のとき(無音・帯域に 何も無い)まで「無限に卓越したピーク」と報告していた。この 2 つの数は docstring のとおり「何も無くてもピーク周波数を返してしまう」ことへの 正直さの指標なのに、いちばん嘘になる向きに振れていた。0/0 は 0.0 が答え。 (2026-09-05: Linux / numpy 2.5.2 で表面化。旧版はフィルタの残差が わずかに残って med > 0 になっていただけで、不具合は前からあった。)
annotate.py
- L3095 — ★句読点(。、)は回さず右上へ寄せるのが本来だが、ここでは寄せない —— できないことを黙って近似せず、docstring に書いて残す。 縦書きで右上へ寄せる字(句読点)。横組みでは字の左下に来る点が、 縦組みでは右上に来る —— 回すのではなく位置を動かすのが組版の作法。 Windows の
@ 付きフォント(GDI が face 名で選ぶ縦組み用の顔)は、これを font 側でやってくれていた。Pillow はフォントをファイルパスで開くので @ の顔には到達できず、HarfBuzz の direction="ttb" も Raqm が入って いる環境と入っていない環境で結果が変わる(この機械の Pillow 12.3.0 は features.check("raqm") が False)。プラットフォームで揃うほうを選ぶ という方針に従い、ここは合成で寄せる。
api.py
- L587 — ★
annotate.overlay_mask は 意図的にトップレベルへ出していない。同名の imgio.overlay_mask が既に fs.overlay_mask として公開されており、引数も 意味も違う(imgio = 生 RGB・mask>0.5・fill/margin / annotate = 役割名の色・ 重み [0,1] も可・形の不一致を拒否)。同じ名前に別の約束を載せると、呼び手は 例外ではなくもっともらしく違う絵を受け取る。公開 API の破壊的変更は 独断でしないので、役割つきの方は fs.annotate.overlay_mask で引く。
- L1346 — ★ いまのところカラー画像に対して正しい呼び方が存在しない: まとめて渡すと 色が混ざり、チャネルごとに 3 回呼ぶと自己正規化する op が各チャネルを 自分の最大で割ってチャネル間の比を壊す(灰色エッジ法の角度誤差が 自前 Sobel 1.03 度 -> 画像ごと 4.17 度 -> ch ごと 27.86 度、ゼロ点 29.14 度)。 どちらに倒すかは契約の決めなので、ここでは既定の数値は 1 つも変えず、
on_error="raise" のときだけ拒否し、既定では台帳に記録して見えるようにする。 詳細と選択肢は docs/KNOWN_ISSUES.md。
astrostack.py
- L156 — ★仮説の検定: 「1 キャッシュライン(64B)に収まるあいだは移す価値が無い」を 予想したが 外れた。float32 は境目 K≈17-19 で 64B(K=16)に近いものの、 float64 は予測 K=8 に対し実際は K≈23-25(約 200B)。バイト数ではなく 要素数で決まっている —— 1 要素あたりの取り出し費用が支配している。 枚数が少ないうちに移すと逆に遅い(float64 K=5 で 1.4 倍遅い)ので、 境目は必ず要る。
-
| L379 — ★MAD が 0 に潰れたのに画像は平坦でない = 量子化(2026-09-08、 poc_thermal_radiometry が踏んだ)。整数の DN では |
x-med |
も整数に なるので、返せる sigma は 1.4826 の倍数だけ —— σ=0.5 の実写相当で 0.0、σ=1.0 と σ=1.983 が同じ 1.4826。黙って 0 を返すと しきい値が背景と同じになり、下流(star_detect)が何も見つけない。 ここは値を返す入口なので raise せず声を上げる(呼び手が method=”clip” を選べる)。refuse するのは答えを出す側 = star_detect の役目。 |
- L586 — ★ ショットノイズの唯一の入口。photons_per_unit=1 で「期待値 = lambda」。
- L675 — ★ field_seed は固定(同じ空)、seed だけ振る(別の観測)。
- L746 — ★この門のコメントは 2026-09-08 まで「完全に平坦 = 雑音が測れない」と 書いていた。前提のほうが間違っていた —— σ が 0 になる道はもう 1 本 あって、整数の DN で MAD が潰れる場合(σ=0.5 相当の実写で 0.0)。 平坦でない画像で空を返すのは保守的な答えではなく誤った答えで、 実際 200x200 の整数フレームに植えた 2 個の点目標が 0 個と返っていた。 平坦なら空(星は無い)、平坦でないなら拒否する、と道を分ける。
- L1606 — ★ 同点のときは生の票が多いビンを選ぶ。3x3 の平滑は真の山の左右 どちらから見ても同じ和になるので、平滑値だけで argmax を取ると 「山の隣の空ビン」が選ばれうる —— 実測でまさにそれが起き、真のずれ (-0.087, +0.996) の票 7 + 4 が bin 境界で 2 分されたうえ、中心が 1 ビン ずれて票 0 になった(frame_align が「重なっていない」と誤って fail-closed した)。1e-6 の重みは平滑値の刻み(1/9)よりはるかに小さい ので、本当に差があるときの順位は動かさない。
- L1629 — ★2026-09-08: 2 番手の山の高さも返す。星野なら山は 1 つだが、 繰り返し構造(網点・格子・織物)では格子ベクトルぶんずれた所に同じ高さの 山が並び、そのどれを選んでも「全員が賛成する」= inlier_ratio が 1.00 に なる。賛成率は「答えが正しい確率」ではないので、山が 1 つだったのかを 別の数で出す(0 = 単峰、1 に近い = 等価な候補が他にもある)。
backend_safe.py
- L436 — ★feature op は ndarray でなく numpy の スカラを返すので、上の分岐は一度もそれを見ていなかった: NaN/Inf の測定値(例えば退化フレームに対する sk_blur_effect 内の 0/0)が api.apply からそのまま流れ出ていた。非有限のスカラも sort フォールバックへ洗い流し、宣言している「有限·sort として妥当」の保証が feature/contour のスカラにも実際に効くようにする。
backends.py
- L23 — ★
_safe フォールバックは最後の手段であり、死んだ op を隠しうる。out_sort==”image” では backend_safe.fallback がクリップした入力を返すので、どんな入力でもライブラリ呼び出しが例外を投げる wrapper が、進化 / difftest / coverage には失敗ではなく「動く恒等 op」に見えてしまう。実行時の頑健性は保つが、劣化は検出可能にしてある: 握り潰した例外はすべて共有のフォールバック台帳に記録し、strict モードでは代わりに再送出する。2026-09-02: 台帳 / strict スイッチを backend_safe へ下ろし、他の 23 個の backend ファイル(各自の private な _safe を持つ)が同じ場所へ報告するようにした —— それ以前は、24 の wrapper 族のうちこのモジュールだけが記録していた。以下の名前は、ここから import する呼び手やテストのための薄い別名として残す。
- L812 — LBP の符号化。★2026-09-08 まで
b は本当に何もしておらず、 method は 'default'(回転不変でない)に固定だった。実写の テクスチャ(brick / grass / gravel)で測ると、異方な素材では 回転で動く量が素材間の距離の 9.64 倍になり、'uniform' に替えると 1.72 倍まで下がる(examples/poc_real_texture_invariance.py)。 選べないと下げようがないので b を割り当てた。閾値の表にして あるのは、同じ軸で分岐が増えるときの規約(入れ子の if にしない)。 b=0.5(既定)は従来どおり 'default'。
- L1028 — ★cv2 に bool 配列を渡すと
cv2.Laplacian がヒープを壊し、後続の無関係な op でプロセスが死ぬ(2026-09-05 Fable レビュー、Windows で 100 回中に SIGSEGV を 自分でも再現、exit 127)。facade は dtype を契約に揃えるが、op.fn 直接経路 (テスト・coverage・進化ループ)は素通しだった。族の入口で float64 に揃える。
backends_auto.py
- L594 — ★キャンバスを変えない(reshape=False)+ 枠外は鏡映(mode=”reflect”)。 角度は -45°..+45°(a=0.5 で 0°)。四隅には元画像が 折り返して 写り込むので、帳票の傾き補正 (deskew) のように「枠外は背景色で 埋めたい」用途にはそのままでは向かない(既知の設計判断であって バグではない — 詳細と使い分けは
ops._rotate_img の docstring)。
- L617 — ★ただし戻り値の shape は 入力と同じキャンバスに保つ。この registry の image は「段間で無条件に繋がる」契約で、shape を変えると評価器が 目標画像と突き合わせられずに落ちる(実測: 目標サイズ版が (70,50) を 返した瞬間
test_evolve_is_reproducible_given_seed が “operands could not be broadcast together with shapes (70,50) (64,64)” で失敗した)。そこで Ht x Wt にリサンプルした像をキャンバス左上に置き、 余白は 0、はみ出す分は切る —— 「画像が今 Ht x Wt 画素である」ことは そのまま見える。
- L1111 — ★2026-09-02: 返していたのは
np.where の 整数画素座標 そのもので、 sub_pix を名乗りながらサブピクセル精度が無かった。放物線当てはめ による法線方向の精密化を追加(core ops._edges_sub_pix と同じ 共有ヘルパ。同名 op はレジストリで後勝ちなので、実際に走るのは こちら —— core だけ直しても効かない)。 実測(真の位置が列 20.37 の合成ステップエッジ、a=0.2): 旧実装の 返す列は {20.0, 21.0} で平均絶対誤差 0.500 px、精密化後は {20.324, 20.370} で 0.0228 px(約 22 倍改善)。 点の個数・連結成分の分け方は不変(座標が 1 px 未満動くだけ)。
- L1270 — ★b >= 0.75 で 4 方向(0/45/90/135 度)の平均を取る。既定 b=0.5 は 従来どおり 0 度だけなので、既存の結果は 1 ビットも変わらない。 効くかどうかは a(共起距離)で変わる(poc_real_texture_invariance の節 6、実写 3 素材): 等方な素材には短中距離で効き、異方な brick には 距離 4 でだけ効く(振れ幅/分解能 3.13 -> 1.54)。距離 1 では brick は
- L1275 — 逆に悪化(0.30 -> 0.56)。★根っこは距離を伸ばすと分解能そのものが 0.0328 -> 0.0122 と潰れること。
- L1482 — ★2026-09-02: この 2 つは
{"kind": "zoom"} を共有していたため 完全に同一 の実装で、しかも 2 つとも b を使っていなかった(実測: 同一入力に対する 最大差 0.0、b=0 と b=1 の差 0.0)。HALCON では factor 版が 2 つの倍率、 size 版が目標サイズを取る 別物 なので、kind を分けて実態を名前に合わせた。
- L1555 — ★2026-09-02: 旧仕様は out_sort=feature / metric=”area” で、実体は
np.mean(mask) = 画像に占める面積比。HALCON の area_center は (Area, Row, Column) を返す op なので、(1) 中心を返さない (2) 面積が画素数 ではなく比率(= 解像度依存)という二重の食い違いがあった。1 スカラでは 名前を満たせないため、ncc_locate と同じ match sort の 1-D ベクトル にして (面積比, 行, 列) を返す。match / feature はどちらも終端 sort (候補は identity のみ)なので、ゲノム→op の写像は動かない。
backends_decomp.py
- L142 — ★BLAS のスレッド上限をループの外に 1 回掛ける。ここは work_max=64 に 抑えた正方行列を最大 60 回 SVD する場所で、この repo で分解時間の大半を 使う(スイート 1 回で 30.7 秒 / 分解合計 31.4 秒、svd 23,987 回 = 98%)。 64x64 の SVD は 24 スレッドだと 1 スレッドの 3.9 倍遅い —— 分解の中の GEMM が 小さすぎて同期の費用が計算量を上回るため(表は fsthreads の docstring)。 1 回ごとに囲むと仕掛けの 2.4us を 60 回払うので、ループの外に置く。
- L206 — ★
ev[0] は代数的に最大の固有値であって、絶対値最大ではない。 明るい稜線では主曲率が負なので ev[0] は絶対値の小さい方になり、 稜線上で 0・両脇で 1 という逆の応答だった(2026-09-05 Fable レビュー、 実測 [1, .64, 0, 0, 0, 0, .64, 1])。説明どおり絶対値最大を取る。
backends_r3.py
- L46 — ★2026-09-05 まで
except Exception: out = None で握り潰していた。 登録時に外側へ backend_safe.guard が掛かるが、内側で例外を消すと外側は 何も見ない —— strict mode でも例外が出ず、台帳にも残らない。 2026-09-02 の「24 族中 1 族しか台帳に届いていなかった」監査の取りこぼし (Fable の敵対レビューが 5 族目として指摘)。例外はそのまま外へ出す: 外側の guard が記録し、sort に合う値へ落とし、strict なら再送出する。
backends_scipy.py
- L198 — ★lambda >= ~12 で scipy が「boundary conditions did not converge」を投げ、 guard の fallback = 恒等になっていた(旧 1+40a は a>=0.3、既定 0.5 を 含む 7 割が恒等。2026-09-05 Fable レビュー)。説明も 1〜11 に合わせた。
backends_typed.py
- L505 — ★2026-09-05 まで
tools/chain_fuzz(非同梱)を sys.path 操作で読んでいた。 wheel では失敗し、下の build() が黙って [] を返すので tb_* 143 op が消えていた。
blob2d.py
- L287 — ★符号に注意: 頂点は (row, col) の順で並んでいるので、
_monotone_chain が返す向きは (row を x と見た) 反時計回り = 画面では時計回り。内側は 外積が非負の側になる(<= 0 と書いて全物体 solidity 0 を出した)。
- L587 — ★収縮だけでは片側しか出ない。番号の小さい物体は、隣に番号の大きい 物体が来ても近傍の最小値が自分のままなので「内部」と判定される (2026-09-06 実測: 1 と 2 が接する列で 1 の側の輪郭が消えた)。 膨張と両方見れば「近傍に自分と違う番号がある」の対称な判定になる。
calib.py
- L178 — ★ この門が実カメラでは発火しないことを 2026-09-06 に実測した。歪みの 無い合成では設計どおり働く(傾き 0 度で比 3.8e-14、0.05 度で 8.6e-10、 どちらも拒否)。ところが現実的な樽型歪み k1=-0.18 を入れると、平面 ホモグラフィのモデルがそもそも合わなくなり、比が傾きに関係なく 1.9e-06 前後に張り付く(0 度 1.916e-06 / 0.05 度 1.935e-06 / 0.2 度 2.005e-06)。
- L184 — ★ 条件は 2 つ揃ったときだけ: 歪みがあることと、視点間で板が横に 動くこと。どちらか片方なら門は設計どおり鳴る(切り分けは tests/test_calib.py の 3 本)。そして実際の校正セッションは、板を手で 動かして撮るのだから必ず両方が揃う。 しきい値を上げれば済む話でもない —— 歪みありでは 完全退化 1.92e-06 と傾き 2 度 4.42e-06 の差が 2.3 倍しかなく、 分ける線が引けない。よって: * しきい値はそのまま(歪み補正済みの点なら正しく効く) * 比そのものを
orientation_rank_ratio として返す * 実際に止めている後段の門に「板を傾けよ」を言わせる(下) 直せない代わりに、判断材料を利用者に渡す。
caltab.py
- L188 — ★このゲートが捕まえないもの: 一枚の平面ターゲットに対する内部パラメータの 誤り(特に fx/fy の比)。平面 1 枚の homography は内部パラメータに 2 つしか 拘束を与えない(Zhang 2000)ので、誤った fy はここで解いている姿勢 6 自由度に ほとんど吸収され、残差はしきい値の下に留まりうる。 実測 2026-09-05: fy を 500 → 300 と誤らせても Linux/scipy 1.18 では RMS 0.90 px (正しい K なら 0.14 px)。同じ入力が Windows/旧 scipy では 6.39 px になり、 最適化の収束先の違いだけで「検出できたりできなかったり」する。 内部パラメータを検証したいなら、視点を 3 枚以上取るか非平面のターゲットを使う。 ここが効くのは「姿勢では吸収できない」不整合(対応付けの誤り、非平面の板)。
champion_to_macro.py
- L193 — ★看板の正直さの主張(「DNA op はロックされた holdout で手作りベースラインに勝ったときだけ追加する」)を強制する —— 以前はこのフラグは表示されるだけで門になっておらず、手作りより悪いマクロが登録され、次の進化で選ばれえた。門は、明示的に上書きしない限りそれを拒否する。
- L87 — ★ビット一致は保証しない(2026-09-05 に訂正)。数学は行ごとに独立だが、
U @ w は BLAS の GEMM なので、行数 M によって縮約の分割やベクトル化 経路が変わり、丸めが変わりうる。実測: CI の py3.11 ジョブに torch を入れた 途端(= 別の OpenMP 実行時が載った途端)にチャンク有無で結果が食い違った。 保証するのは数値的な一致(数 ULP)であって bit 一致ではない。
demops.py
- L97 — ★ 中央値などで埋める選択肢は用意しない。埋めると存在しない平原ができ、 例外を出さずに水を通す。 ただし効果の大きさは正直に書いておく。同じ実データ(東京湾岸 1024x1024、 欠測 3.83%)で 3 通りを比べた最大集水セル数: 流出口 312,108 (29.8%) / 中央値で穴埋め 338,188 (32.3%) / 壁 315,023 (30.0%) 穴埋めは 8% ほど水増しするが、「1 セルが全体の 3 割を集める」こと自体は この地形の実際である(平坦な埋立地は実際に一箇所へ集まる)。 最初に穴埋めだけを見て「この数字は穴埋めの産物だ」と書いたのは誇張で、 対照を取ったら効果は縮んだ。埋める選択肢を置かないのは、 どこが実際の地形でどこが穴埋めか区別できなくなるからであって、 数字が桁で変わるからではない。
- L605 — ★ この遅さは PoC(examples/poc_dem_terrain.py)で 513^2 の天空率に 41.9 秒 かかって初めて気づいた。テストは小さい格子しか使っておらず、 「動く」ことは確かめていたが「使える」ことは確かめていなかった。
- L686 — ★2026-09-08 修正(
poc_stockpile_volume が発見)。視線の標本が np.rint で目標セル自身に丸まると、そのセルの高さを「途中の地形」 として自分と比べることになる。t < 1 なので分母 dist*t が小さく、 (z-eye)/(dist*t) > (z-eye)/dist は z > eye なら必ず真 —— 目線より高いセルが軒並み自己遮蔽されていた。実測(修正前): 平地に立てた高さ 10 m の柱は 25 m 先・目線 2 m から「見えない」と返り、 目線より低い 1 m の柱だけが「見える」。凸な立体の最高点は外から必ず 見えるので、これは幾何として誤り。標本が目標セルに乗った回は数えない。
- L746 — ★ 台帳の宣言は
points = (N, 3)。スカラを渡すと (3,) になって宣言と 食い違うので、常に (N, 3) へ畳む(2026-09-06 にファザーの TYPEMISS で 露見。地心座標 6 op を足したあとファザーを回していなかった)。 格子のまま (H, W, 3) が欲しいときは :func:dem_geocentric_grid を使う。
-
| L795 — ★縮閉線の内側は測地緯度が一意でない -> 黙って範囲外の緯度を返さず拒否する。 楕円 x²/a² + z²/b² = 1 の縮閉線は (a·x)^(2/3) + (b·z)^(2/3) = (a²-b²)^(2/3)。 等号の外側だけが「法線が 1 本に決まる」領域(2/3 乗は非負なので符号は |
z |
)。 |
evis_fullseye_bridge.py
- L152 — ★The sky is “infinitely” far (measured: 998 in a world whose animal is 0.3 across), and with the sky in view the 3rd/92nd percentiles straddle it, so the panel collapses to two flat colours — sky and everything-else. depth_max cuts the band at a distance that means something for this body, so the scene gets the colour range instead of the sky.
- L171 — ★ego_camera(モデル自身の目)でも eye パネルを出す。ここを ego>=0 だけで見ていたので、 ハエの複眼から描いたのに複眼の絵がコマに入らなかった(2026-09-14 実測)。
- L180 — ★drop frame 0: the event panel has no previous frame to difference against, so it is blank by construction. Keeping it makes the first thing a reader sees a black panel, which reads as “the events never fired” (measured: frame 0 has 960 lit pixels, frame 20 has 35,550). The stats below still count every frame that was rendered.
- L189 — ★distances carry the MODEL’s unit, not metres: the fly world is cm/g/s, so reporting “6.96m” for a 7 cm walk is a lie the caller cannot see.
unit names it honestly.
examplefig.py
- L139 — ★
colorize_depth は float [0,1] を返す。np.asarray(..., np.uint8) で 受けると 0.x が全部 0 に切り捨てられて真っ黒になる(2026-09-06 に踏んだ)。
- L171 — ★例の本文を落とさない。図が出ないのは残念だが、数字は出さねばならない。
- L210 — ★ここで :func:
_to_rgb8 に丸投げしてはいけない。あれは (H,W) を colorize_depth に渡すが、その中で 1 枚ずつ正規化されるので、 全コマ 0 の画と全コマ 1 の画が同じ色になる(2026-09-09 に試験が捕まえた)。 値域を明示して渡すことで、初めて尺度が 1 つになる。
- L275 — ★Pillow は直前とまったく同じコマを 1 枚に畳む(その分の時間は前の コマの表示時間に足されるので、動きの速さは変わらない)。書いた後で 数え、渡した数と違えば台帳に両方残す —— 「72 コマの GIF」と 言いながら中身が 40 コマ、を黙って通さないため。
- L339 — ★2026-09-08: パネルが小さいと題が入らず、
annotate_figure_grid が (正しく)拒否して図が 1 枚黙って消えていた。29×19 の core 格子や 24×24 の縮小マップは PoC で普通に出るのに、エラーは 「題を短くしろ」と言う —— 実際の直し方は「パネルを大きくしろ」。 2 人の担当が独立に同じ穴に落ちた(看板の scene 図が 1 枚消えた例あり)ので、 呼び手ごとに拡大を書かせず、ここで 1 度だけ最近傍拡大する。 最近傍にするのは、拡大で値を作らないため(補間すると図の上で 存在しない中間値が生まれ、疑似カラーが嘘をつく)。
examples/acoustic_condition_monitoring.py
- L467 — ★放物線補間には整数へ引く偏りが残る(ピークが sinc 状なので二次で近似 しきれない)。0 から 1 まで振って偏りを実測し、S 字になることを示す —— 「サブ標本まで読めた」で終わらせると、この偏りが黙って結果に乗る。
examples/annotate_paper_tour.py
- L51 — ★EXTEND: text と path を自分の図の文字と折れ線 (x, y) に差し替える
examples/blas_thread_budget.py
- L117 — ★ここが要点。96x96 は「小さいから速い」のではなく、 小さいからこそ多スレッドが損になる大きさ。ループの外に 1 回置く (1 回ごとに囲むと、絞る仕掛け自体の費用を 30 回払うことになる)。
examples/blob_split_tour.py
- L98 — ★実測(honest): 高さ 2 < h の棒にも種が立つ。blob_seeds は残差
f - R > 0 を種にするが、 成分ごとに背景 0 で再構成すると山の高さ M < h の成分は R = M - h < 0 になり、成分の 全画素と背景 1 px の縁まで残差が正になる(skimage の h_maxima は 残差 >= h で弾く)。 実装は直さず報告する。ここでは棒の種を外して「種の無い塊」の経路を検算する。
- L129 — ★実測(honest): 割れ目は交線に乗らず、番号の大きい種の側が谷に沿って食い込む。 blob_split は段ごとの膨張で「両方の領域に触れた画素」を grey_dilation の max(= 大きい番号)に 与えるので、8 連結の斜め連鎖で番号の大きい領域が谷線に沿って数列ぶん侵入する。種番号を 入れ替えると侵入の向きも入れ替わる(幾何ではなく番号の偏り)。実装は直さず報告する。
- L153 — ★実測(honest): 教科書の h-maxima なら「低いほうの山のそびえ(16 - くびれ 10.07 = 5.93)」 を h が超えた時点で種が 1 つに融合する。blob_seeds は残差 > 0 を種にするので、残差 = min(h, そびえ) > 0 が常に成り立ち、低い山の種は h では消えない。融合するのは 「高いほうの山 - くびれ(22 - 10.07 = 11.93)」を h が超えたとき —— 参照する山が逆。
examples/coherence_scanning.py
- L166 — 6) ★ 位相シフト法との突き合わせ # —————————————————————— #
examples/dem_geodesy_tour.py
- L49 — ★リポジトリ直下を通しておかないと
demops が見つからない(この例は fullseye を import しないので、パスフックが効かない)。
- L61 — ★EXTEND: 自分のタイルの北西角に差し替える(ここは東京付近)。
- L131 — ★正直な内訳: Bowring の 1 回反復は楕円体面では 1e-9 m だが、高さが上がるほど 誤差が増える(実測 8848 m で 8e-7 m、20 km で 4e-6 m)。docstring の 「1e-12 度 / 1e-7 m」は地表付近の値であって、成層圏の高さでは成り立たない。 地形(標高 < 9 km)の用途では 1e-6 m で、ここでは 1e-5 m を閾値にする。
- L160 — ★EXTEND: dem を実データに差し替える(行 0 が北)。ここは既知の傾斜面。
examples/dem_terrain_analysis_tour.py
- L46 — ★リポジトリ直下を通しておかないと
demops が見つからない(この例は fullseye を import しないので、パスフックが効かない)。
- L59 — ★EXTEND: セル寸法 [m]。実データでは dem_cell_size_webmercator(zoom, 緯度) で出す。
- L158 — ★正直な観察: 斜面の途中に欠測があるとき、その北隣は outlet でも欠測へは落ちず 南西(有限の落差がある方向)へ行く。実装は「他に下る先が無いときだけ欠測へ」で、 docstring の「欠測へ向かう流れを許す」より狭い。ここでは印字だけで assert しない。
examples/piv_flow_from_particles.py
- L27 — ★repo 直下のモジュール(pivops)を import するので、チェックアウトから そのまま走らせても通るように repo 直下を先頭に置く。他の例と同じ作法。 これが無いと
py -3.11 examples/<name>.py が ModuleNotFoundError で落ちる (2026-09-09 実測: 走らせる門が無かった 83 本のうち、落ちたのはこの型の 2 本だけ)。
examples/poc_allsky_cloud_cover.py
- L104 — ★最後の 3 つは薄い雲(光学的厚さちがい)。しきい値を上げると 薄いものから順に落ちる —— 4 節の階段はこれで出る。
- L142 — ★立体角の重み。dΩ/dA = sinθ/(f²θ) —— 等距離射影のヤコビアン。
- L524 — ★2026-09-08: “equidistant” は 1-D の
create_funct_1d_array(等間隔の標本 から関数を作る)に当たるようになった —— ops1d を op_find から引けるように した副作用で、投影モデルとは無関係。語が同じだけで穴は埋まっていない ので、「投影の族に無いこと」を見る形に直した(語の一致で判定しない)。
examples/poc_asbuilt_wall_deviation.py
- L497 — ★漏れていたのは倒れではなくふくらみ。閉形式で predict_bulge が 1 次の係数として返す量が、そのまま偽の倒れと偽の平面内の振れになる。
- L555 — ★閉形式にはふくらみが吸われた分(§6)を入れた実効の倒れを渡す。 入れないと f=0 の 1 点だけが 1.2 mrad ずれ、予測が外れたように見える。
- L660 — ★雑音だけの床。ふくらみゼロの壁で同じ読み方をすると、これが出る。
examples/poc_astro_photometry.py
- L322 — ★ ここで一度間違えた: 「scale=2 だから明るさも 1/4」と思って flux/4 を書き、 -74.89 % を出した。保存則(上の 6.1e-14)がそれを弾いた。画素あたりの 明るさは 1/4 になるが、星の総和は変わらない。
- L423 — ★ ここで一度 assert を落とした: 上の表の rms(1 回の合成・孤立星 8 個)で 良 6 枚 0.306 % vs 良 12 枚 0.324 % = 0.947 倍が出た。理論 1.414 の 反証ではなく、あの rms が「星ごとの系統ずれ」と「雑音」を足したもので、 標本 8 個では雑音だけを取り出せない、という意味だった。段 1 と同じく 反復を積んで星ごとの平均を引くと、初めて雑音だけが残る。
examples/poc_barcode_1d.py
- L806 — (d) ★measure_pos のエッジ本数が sigma に非単調に依存する。
examples/poc_battery_ct_degradation.py
- L316 — ★
sdf_offset はスカラのみなので、場でずらすには格子を歪めて評価する。
- L334 — ★積層が缶を突き抜けないように、たわんだ端板が許す高さまで局所的に圧縮する (実セルでも電極は加圧されて縮む)。これをしないと、背の高いガス空隙のところで 端の層が缶に食われ、層数の比較が壊れる(最初そうなった)。
- L612 — ★層は「立ち上がりの縁の数」で数える。
vol_wall_thickness の対 (立ち上がり -> 立ち下がり)で数えると、缶の内面のすぐ内側に余分な 立ち下がりが 1 本入るだけで対がずれ、健全なセルでも 17 -> 16 に落ちる。
examples/poc_battery_electrode_tortuosity.py
- L136 — ★公開経路に無い処理: voxel 空間の 6 近傍隣接グラフ。fullseye は 3-D の # 連結成分(vol_label)も距離変換(vol_distance_transform)も持っているが、 # 「空隙を通り抜ける経路」を扱う口(測地距離・輸送)は無い。 # ————————————————————————— #
- L248 — ★64 voxel のスライスをそのまま渡すとパネル幅が 64 px しかなく、 題の文字が入らずに図ごと落ちる(examplefig は黙って諦めない)。
- L269 — ★固相を 0 のままにすると log10(散逸) は負なので固相がいちばん明るく 塗られる(2026-09-08 に一度そう出した)。固相は空隙の下位 2 % に合わせる。
examples/poc_beam_modal_video.py
- L629 — ★衝突: fps 48.5 では照明の折り返しが f_1 = 3.00 Hz にぴったり乗る
examples/poc_bev_sensor_fusion.py
- L135 — 置いてある。★これは飾りではない: * 面をセル境界に載せると、面の返りが雑音で隣へ半分こぼれ、適合率が discretisation だけで 0.5 に落ちる。 * 面をセル中心に載せると、今度は真値のほうが浮動小数の丸めで 入ったり入らなかったりする(実際に踏んだ: 側壁の返る列が真値から 外れ、偽占有 133 セルのうち大半がそれだった)。 中間に置けば両方が起きない。
h は 0.2 m の倍数を避けてある —— 高さの量子化を見せるため。lx/ly は 0.1 m の奇数倍にする。
- L564 — ★誤差は 世界の z 軸まわり(= place と同じ)。
R_wc @ rz と 書くと光軸まわりの roll になり、再投影誤差が 1/5 に化ける (2026-09-07 に踏んだ: 0.98 px と出て、幾何の予測 f·tanθ と合わず発覚)。
examples/poc_bilateral_asymmetry.py
- L585 — ★穴 D の門をそのまま渡せる形にしておく(margin が先に潰れ、角度が後から跳ぶ)。
examples/poc_bump_coplanarity.py
- L147 — ★本物の低次不良(ダイアタッチのボイド = 中央がなだらかに沈む)。 わざと厳密な 2 次にしない —— 2 次にすると当てはめが定義上 100 % 吸ってしまい、「どれだけ吸われるか」という問いが自明になる。
-
| L306 — ★±SPEC_UM で clip してから渡す。examplefig の発散配色はパネルごとに max |
v |
で正規化するので、clip しないと 3 枚の色の意味が揃わない。 |
- L445 — 6. ★引きすぎの害 —— 本物の低次不良を吸う # ————————————————————————— #
- L540 — (e) ★台帳経由の surface_form_error は PV の float しか返らない
examples/poc_cad_scan_deviation.py
- L434 — ★台帳の out アダプタが dict を (R, t) に切り詰めるので rmse は届かない
- L893 — 章 6: ★欠陥が位置合わせを引く —— 剛体 6 次元への射影で予測する # ————————————————————————— #
- L1099 — ★欠陥を入れない —— 入れると第 6 章の datum ずれ(0.107 mm)が 点移動の下駄になって「初期角度で壊れた量」と混ざる。
- L1252 — ★真値が 0 の対照群で「%」を出すと 0 割りで意味の無い巨大な数になる。 面積は mm^2 のまま並べ、%は真値が意味を持つときだけ添える。
- L1263 — ★1 本の実行の差を「効いた」と読まない —— 種を振って散らばりと比べる
- L1353 — ★穴が塞がったら鳴る assert。実際 2026-09-07 に鳴り、この行を書き換えた: 「円筒穴・面取り・フィレットが組めない」という指摘を受けて plane / cylinder / torus / capsule が足された。指摘が道具を変えたので、記録を残して先へ進める。
examples/poc_camera_calibration.py
- L150 — ── 校正(自前の最小バンドル調整。★ 穴 (e))──────────────────────────────────── #
- L176 — ★ 穴 (d): camera_calibration の画像点は (row, col)。project_points は (x, y)。
- L304 — ★ 穴 (b): reprojection_error は歪みを知らない。真値を渡しても 0 にならない。
- L525 — 2. ★ 主役: 再投影 RMS はほぼ同じなのに fx 誤差が 1 桁以上違う
- L533 — 3. ★ 相殺の仕組み: fx の比と Z の比が一致する
- L539 — 4b. ★ 正直な負けの記録: 狭い視野 + 雑音 0.30 px では主点を推定するより 画像中心に固定するゼロ点 B の方が正しい(上回れない条件が実在する)
- L555 — ★ 穴 (c): 歪んだ点なので止めたのは退化門ではなく後段の非有限 K の門。 その文言に「板を傾けよ」が入っていることまで確かめる(2026-09-06 追加)。
- L563 — 5b. ★ 穴 (c3): 閉形式は歪みのぶんだけ系統的に外れる(初期値専用)
- L567 — 6. ★ 穴 (b): reprojection_error は歪みを知らない -> 真値を渡しても大きい
- L573 — 7. ★ 穴 (a): 内部パラメータ推定はファサードから見えない
examples/poc_cell_counting.py
- L853 — ★指定できる最小の h は 0.05 x max(距離変換)。画像の中に大きい細胞が 1 つあるだけで、画像全体の h の下限が上がる(op の仕様による結合)。
- L1041 — ★この PoC の見出し。偏りの線が 0 を横切る場所で、分割誤りは谷になっていない。
- L1330 — ★過統合と取りこぼしは別物 —— くっついても「消えて」はいない
- L1358 — ★最適な h は密度で動く(偏り基準か 1対1 基準のどちらかで必ず動く)
- L1361 — (5) ★計数が合っていて分割が全部外れている点が実在する 偏りが 3 % 未満なのに、分割誤りが多く残り、1 対 1 対応も最良から離れている。
- L1387 — ★指定できる最小の h が大きさ比とともに上がる(道具の仕様によるスケール結合)
- L1427 — (10) ★道具の穴が「まだ在る」ことを機械で確かめる(直ったら落ちる = 良い落ち方) (a) 進化 op の距離変換は最大値で正規化される
examples/poc_change_detection_misreg.py
- L947 — ★1 枚のグラフ: 残留ずれ vs 偽陽性(掃引の線 + 登録結果の点)
examples/poc_cold_chain_excursion.py
- L568 — ★ピークを探す窓は次の扉開閉の手前まで。ここを広く取ると、τ が大きい ところで次のパルスの立ち上がりを拾い、「崖が来ない」ように見える (2026-09-08 に 200 分の窓で踏んだ: y=53 の実測が 153 分に伸びた)。
- L947 — ★視線方向(D 軸)を幅にする。(t, y, x) のまま投影すると D = 時間 720 になり、返る (H, W) = (60, 12) の細長い絵しか出ない。
- L1006 — ★「当たった」のが規約のおかげか偶然かを分ける: 各点を ±1 m 揺らして数える。
examples/poc_colocalization_crosstalk.py
- L355 — ★裾落ちの予想: しきい値 T より下の Gaussian の裾は領域に入らない。 ピーク p の点のうち領域内の蛍光は 1 − (T − 台)/p(2-D Gaussian の 体積の閉形式)。台 = 細胞質 + 背景(+ 漏れ込みぶん)、p は PSF で σ_ves²/(σ_ves²+σ_psf²) 倍に潰れる。
examples/poc_colormap_readability.py
- L343 — ★段差の列で読み取れる差は Δ + 画素 1 個ぶんのランプ —— これを 忘れると崖を 2 倍高く見積もる(最初そう書いて 0.57 vs 実測 0.30 になった)
- L406 — ★真の勾配で割る。割らないと「場が急なところ」を境目と数えてしまう
- L657 — ★色数を超えると既定で拒否される(この PoC が指摘して同日に fail-closed になった)。ここは「循環したらどうなるか」を測るのが 目的なので cycle=True を明示する —— 明示させること自体が対策。
- L732 — ★この PoC の指摘で同日に直った。名簿の基準が「明度の単調さ」だけだったので、 明度は単調なのに色差の刻みが粗い cividis が「安全」と名乗っていた。 いまは色差の一様さも基準に入り、cividis は CVD_SAFE へ移っている。
examples/poc_compound_eye.py
- L301 — ★PoC の門(tests/test_poc_scripts_run.py)は exit 0 に加えて “PASS” の印字を 要求する(合否を計算したのに捨てる門を防ぐ規約)。以前は “OK:” と書いていて、 台帳に登録した瞬間に「exit 0 だが PASS を印字していない」で落ちた。
examples/poc_crop_phenotyping.py
- L209 — ★乱数は必ず (n_plant, NESTED_MAX) の形で先に引く。葉数ごとに引く数を 変えると乱数列がずれ、n_leaf を 1 増やしただけで別の群落になる (2026-09-07: 植被率が葉数に対して単調でなくなり、崖が測れなかった)。
- L525 — ★
grid_coords はボクセル中心を置く(中心間隔 = span/res であって span/(res-1) ではない)。最初 span/(res-1) を掛けて球で面積 +12 %、 体積 +18 % の誤差を出した —— 単位の取り違えは「もっともらしく間違える」。
- L971 — ★真値も葉角分布もこの節が見ている群落そのものから取る。基準条件 (葉 7 枚)の k を使い回すと、上位葉ほど立つ勾配のぶんだけ真値がずれる。
- L980 — ★最大の平面が地面とはかぎらない(群落が閉じると草冠の一部が最大になる)。 最初の平面をそのまま地面にした版は標高 1.69 m と答えた(2026-09-07 に踏んだ)。 いちばん低い平面を採る規則を入れて初めて安定した。
- L1007 — ★対照群: 同じ式を真の法線(バッファが持っている)に当てる。
- L1136 — ★
occupancy_grid の軸は (x, y, z)。render_volume_projection は 軸 0 を視線方向として潰すので、天頂図が欲しければ (z, y, x) へ入れ替える。 入れ替えずに呼ぶと「側面図のつもりの天頂図」が出る(黙って間違える型)。
examples/poc_ct_fidelity.py
- L342 — ★この PoC の見出し。零点 A(水平線)と零点 B に FBP が交差するところが 目で見える。横軸は投影数(左が疎)。 横軸は log —— 交差が起きるのは疎な側(12〜45 本)で、線形軸だと左端に 潰れて肝心のところが読めない。
- L407 — ★2026-09-06 に塞がった。以前は「検出器を倍にすると質量欠損が 2 倍以上 改善する」= 壊れていることを固定していた。いまは 2 つを固定する: (1) 質量がそもそも保存されている (2) 検出器の数では動かない (n_detectors は検出器の幅であって標本化の細かさではないので、 対象が収まっていれば増やしたぶんは空のビンが増えるだけ)。
examples/poc_ct_void_morphology.py
- L233 — ★ダイの占有で代用すると、粗いボクセルで厚み 50 µm のダイがボクセル中心の あいだに落ち、基準そのものが消える(60 µm・位相 2/3 で実際に 0 個になった)。
- L558 — ★全部 nan(どの位相でも測れなかった)を np.nanmean に渡すと警告が出る。 「測れなかった」は平均の対象ではないので、ここで明示的に nan にする。
- L634 — ★nan(測れなかった点)は落として引く —— 折れ線 op は非有限値を拒否する。
- L808 — ★穴が塞がったら鳴る。2026-09-07 に鳴り、この節を書き換えた —— 「esdf は長さ 3 の voxel_size を受けるのに、その出力を引く側が立方限定」という指摘を受けて、 query_distance(と occupancy_grid)が軸ごとの res を受けるようになった。
- L917 — ★体積率は粗いボクセルでも保たれ、先に死ぬのは形の指標(予想が外れた側)
examples/poc_datacenter_thermal_field.py
- L221 — ★2026-09-08: この PoC が「散らばった点から場を作る口が無い」と 記録したので
fs.interp_scattered を足した。凸包の外に出た点は op が マスクで返す ので、isfinite で当てずに済む (fill_value を有限値にしても壊れない)。
- L862 — ★「偽の峰 0」が本当に数えているのか、門を壊して確かめる
examples/poc_dem_terrain.py
- L42 — ★リポジトリ直下を通しておかないと
demops が見つからない(この例は fullseye を import しないので、パスフックが効かない)。
examples/poc_dfm_thickness_overhang.py
- L284 — ★向き(表裏)は巻き順で決まるが、marching cubes の巻き順は入力の符号規約で反転する。 閉じたメッシュなら符号付き体積で一意に決まる —— 目視でなく式で決める。
- L379 — ★格子の原点を壁の面にそろえてはいけない。3.0 で切ると壁の面が ちょうど voxel の境目に落ち、掃引 8 点すべてで誤差 0.000 mm になって 「量子化は起きない」という嘘の結論が出る(2026-09-07 に一度そう書いた)。 実際のメッシャは部品の面に格子をそろえてはくれないので、非整合な原点にする。
- L455 — ★h を「T/h が整数」になる点だけで振ってはいけない。整数比では占有ボクセルの 枚数がぴったり T/h 枚になり、誤差 0.000 mm が並んで「量子化は起きない」に 見える(2026-09-07 に一度そう書いた)。h は連続に振る。
- L705 — ★45 度ちょうどの傾斜方向は入れない —— 板の裏 2349.7 mm^2 が自分もしきい値に 貼りついてしまい、「どの向きが良いか」の表が段差の話に乗っ取られる。
- L824 — ★穴が塞がったら鳴る assert。2026-09-07 に鳴り、この行を書き換えた —— 「面ごとの面積が無い」という指摘を受けて face_areas / mesh_volume / boundary_vertices が足された。塞がったことを記録して先へ進める。
examples/poc_dic_strain.py
- L104 — ★正規化は基準画像で決めた 1 つの定数で行う。像ごとの最大で割ると、 変形で最大値がわずかに動くだけで全体の明るさが変わり、輝度不変を 仮定する推定器(Lucas-Kanade / Horn-Schunck)に無関係な誤差が乗る。
- L211 — ★所見を固定する: 変形は補間ではなく斑点の再描画なので、整数シフトは 厳密に一致するはず。ここが崩れたら 2 節以降の「真値」が真値でなくなり、 測っているのが推定器なのか自分の補間器なのか分からなくなる。
- L247 — ★所見を固定する: 3 つとも「動いていない」と答えるだけのゼロ点に桁で勝つ。 1 つでも 10 倍を割ったら、その推定器はこの場面では使い物になっていない。
- L282 — ★所見を固定する。 (1) piv の偏りは掃引の全域で lk / hs より小さい。※「1 桁小さい」が成り立つのは 2 節の u=0.37 の 1 点(0.0002 vs 0.0042 = 21 倍)で、掃引の最大どうしでは 6 倍程度(piv 0.0015 / lk 0.0088)。ここは最大どうしを 2 倍で固定する。
- L365 — ★所見を固定する。 (1) lk と piv は 100 µε を ±30 µε で回収する(実測 +9.1 / +0.4)。
- L369 — (2) ★hs は 100 µε で 22 µε しか返さない —— 上の「符号と桁は出る」は hs には当てはまらない(正則化が一様ひずみそのものを平らにする)。 主張と実測の食い違いなので、実測のほうを固定しておく。
- L413 — ★所見を固定する。 (1) 2 度の回転は微小ひずみでは理論どおり -609 µε 前後の嘘になる (材料は伸びていない)。鋼の降伏ひずみ 2000 µε の 3 割。
- L438 — ★一様勾配(ε が x の 1 次)では鈍らない —— 対称窓の最小二乗は 1 次関数の 傾きを厳密に返すため。窓の効果を見るには曲率のあるひずみ場が要る。 切欠き先端のひずみ集中がまさにそれなので、ガウス形の集中を仕込む。
- L484 — ★所見を固定する。 (1) lk の尖頭は窓幅について単調に下がる(空間分解能の限界そのもの)。
- L522 — ★1 枚の隅を切って数えると窓の取り方で 2 倍動く。全窓の平均を使う。
- L577 — ★所見を固定する: 偏りは斑点を太くすると単調に減る。3 節で見た lk の偏りは 推定器だけの性質ではなく、スペックルの標本化不足が半分を作っている。 ここが単調でなくなったら「0.01 px」の主張の根拠が 1 本崩れる。
examples/poc_die_tilt_tsv_overlay.py
- L167 — 格子の広がり。★erf の裾(±4σ)まで含めないと、傾いたダイでは外周のビアが z ごとに違う切られ方をして偽の傾きになる。
- L241 — ★台帳経由の vol_label は docstring と違って labels だけを返す (
(labels, n) の n が落ちている。節 9 の (f))。
- L297 — ★ここで MU_SI を引いてはいけない。探針はビアの外では空気(0)を 通るので、生の値がそのまま材料の占有率に比例する。引いて clip すると 端のなだらかな部分が 0 に潰れ、長さが 100.0 -> 98.1 µm(-1.9 %)。
- L484 — ★対照群を引いて「傾きが足したぶん」だけを取り出す(推定器の系統誤差を消す)
- L634 — (f) ★同じ op が、呼ぶ経路によって返り値の中身が違う
examples/poc_dimensional_inspection.py
- L521 — ★ rms を信じてよいか —— 敵対的に 1 点だけ外へ動かす
- L1553 — ★2026-09-06 に「埋もれている」が解消された。以前は
n_reach == 0 (届かないことを固定)だった。いまは届くことを固定する。
examples/poc_document_scan.py
- L271 — ★ 2 値マスクに直接 sobel_dir を当てると勾配方向が 0/90 度に量子化され、 1 点 1 票の方向つき Hough はその 2 本に潰れる(実測: 4 本のうち 2 本が ちょうど 0.00 / 90.00 度)。先にぼかしてから方向を測る。
examples/poc_fabric_defect.py
- L83 — ★マスクの面積はわざと同じくらいに揃えてある。まとめた AUC は陽性画素数で 重みづけた平均に近いので、片方が桁で大きいと「まとめると隠れる」が起きない。
- L119 — ★マスク半径は σ の倍率で個別に決めてある —— 面積を揃えるため。 面積が桁で違うと「まとめた AUC は面積の大きいほうの AUC」に なってしまい、この PoC が測りたい「まとめると隠れる」が 「面積が大きいほうが勝つ」という別の話にすり替わる。
examples/poc_fiber_orientation.py
- L376 — 節 2. ★★素朴な平均が 180 度周期で壊れる # ————————————————————————— #
- L469 — 節 4. ★★重みを選ばないと配向度は必ず小さく出る # ————————————————————————— #
- L499 — ★角度は周期量なので colorize_depth で塗ると 0 度と 179 度が正反対の色に なる。fullseye には循環 LUT の名前は無いが、colorize_flow に (cos2θ, sin2θ) を渡すと 2 倍角の循環 LUT になる(末尾「道具の穴」(f))。
- L693 — ★”coherence” という名前は在るが、信号処理の 2 信号コヒーレンス(別物)
- L724 — (e) ★同じ族の 2 本で入力検査が食い違う
examples/poc_fly_vision.py
- L623 — ★ラミナ段(DC 落とし)を省くと相関が落ちる、を固定する。落ちなくなったら fly_emd_response の側で DC が消えている(仕様変更)なので、この対照を見直す。
- L650 — ★PoC の門(tests/test_poc_scripts_run.py)は exit 0 に加えて “PASS” の印字を 要求する(合否を計算したのに捨てる門を防ぐ規約)。
examples/poc_focus_stacking.py
- L491 — 1. 絵は効いている。★閾値は +3 dB —— 半導体の実画像は平滑金属(ダイ・リード)が 大半で、そこは単一フレームでも合焦しているため、全面が高周波な合成パターンほど AIF の伸びは大きくない(現場の正直な姿。旧・全面テクスチャ場では +14 dB 出た)。
examples/poc_forensics_roc.py
- L396 — ★穴 (a) は「定数地図」なので、絵にすれば数字を読むまでもない。
- L523 — ★この PoC の見出し。いちばん強い検出器の曲線が、保存ボタン 1 回で 対角線まで(そして下まで)落ちる。
- L677 — (4) ★穴 (a): op の argmin 読み出しは、再保存した画像では実質定数地図。 AUC はちょうど 0.5 = 乱数と区別できない。
- L704 — (9) ★穴 (b): 8 画素格子。差が 8 の倍数のときだけ言い当てる(再保存なし)
examples/poc_gear_tooth_metrology.py
- L199 — 撮像系のぼけ。★2-D のガウスぼかしは σ を直に渡す口が無く、進化 op の つまみ a から σ = 0.3 + 2.7 a を逆算して渡す(末尾「道具の穴」(c))。
examples/poc_geodetic_height_frames.py
- L408 — ★往復は「両方同じ向きに間違っている」を排除できない。独立実装と突き合わせる。
-
| L437 — ★予測(測る前に印字する): 傾斜は atan |
∇H |
。h を使うと atan |
∇H+∇N |
。 |
- L464 — ★予測と実測の最大差は「模型の誤り」か「離散化」かを分ける。セルを細かくする。
-
| L584 — ★予測(閉形式): 下り方向が 90 度以上回る ⇔ ∇H・(∇H+∇N) < 0 ⇔ |
∇H |
^2 + ∇H・∇N < 0。測る前に率を出しておく。 |
-
| L644 — ★2 つ目の(こちらが本命の)閉形式。視線は両端の h で引くので、N の線形部は 視線にも地面にも同じだけ乗って消える。残るのは N が弦から離れる量 = |
N’’ |
d^2 / 8。この場の N’’ は 2C(cos^2θ - sin^2θ) なので |
N’’ |
<= 2C。 |
- L1106 — ★
vertical だけは op_find が 5 件返す。中身は 1 つも関係ない (boundary_vertices などの語幹一致)—— 件数で「在る」と言ってはいけない。
examples/poc_interferometry_step.py
- L159 — 3) ★繰り返し測定 — 偏りと散らばりを分ける # —————————————————————— #
- L202 — 4) ★ゼロ点(包絡線の最大サンプル)との比較 # —————————————————————— #
- L274 — 6) ★雑音掃引 — どこで測れなくなるか # —————————————————————— #
- L314 — ★散らばりが小さいことは正しさの証拠にならない
examples/poc_leak_localization.py
- L591 — ★予測 C の検定 —— 漏水位置を細かく振って小数部を散らす
- L726 — ★対照群 —— 反射だけを左右入れ替える。偏りの向きが反転すれば 「遠いほうの継手が偏りの向きを決める」が原因だと言える。
examples/poc_lidar_terrain_change.py
- L406 — ★測れなかった core の面積は土量に一切入らない。有効率で割り戻した値も返す —— 割り戻さないと「静かに欠けた土量」を正しい値だと思ってしまう。
- L694 — ★真値に近い数字が「正しい」とは限らない —— 逆向きの 2 つの誤差を分けて数える
- L823 — ★有効 core が少なすぎるときの LoD は「測った」ことにしない (2 点の標準偏差は数字にはなるが意味を持たない)。
- L826 — ★ここで間引くと C2C が「間引き後の点間隔」を測ってしまい、密度依存が消える (最初に 6000 点へ揃えて書いたら、どの密度でも 0.42 m の一定値になった)。
- L946 — — ★ 合わせた分だけ変化が消える ————————————– #
examples/poc_lightfield_depth.py
- L594 — 2b. ★ 穴 (d): docstring は 0-d と言うが実際は (1,)
- L610 — 6. ★ 穴 (a): 既定 linear は 1.15 を 1.0 側へ引く、cubic は引かない
- L634 — 10. ★ 穴 (e) は 2026-09-06 に塞がった。塞がった状態を固定する側へ 書き換えてある(以前は「警告が出ること」を assert していた)。
examples/poc_livestock_body_volume.py
- L1032 — ★3 台と 6 台は接線の集合が完全に一致する(平行投影では向かい合う 2 台が同じ)
- L1040 — ★奇数 13 台が偶数 16 台に勝つ
- L1054 — ★3-D の凸包は「断面の凸包」の代役にならない(胸囲を大きく外す)
- L1057 — ★2 倍則: 胸囲の誤差が体重で 2 倍になる(残差は 2 次項)
examples/poc_machine_condition_fusion.py
- L184 — (継手, 軸受A, 軸受B, 機械全体) の発熱 [W]。★正常・アンバランス・ゆるみは わざと同じにしてある —— 熱では原理的に分けられない 3 モード。
- L202 — ★軸受と同じくらい熱い。違うのは広がりだけ(両軸受 + 機械全体)。
- L1028 — ★2026-09-08: ここは numpy の rfft を自前で書いていた —— 「片側振幅 スペクトルの口が台帳に無い」と読んだためだが、
fs.spectrum は 前から在った(台帳に出ていなかっただけ)。1 つの層だけ見て 「無い」と決めた例なので、op を使う形に直す。
- L1162 — ★2026-09-08: ここは「台帳に spectrum が無い」と書いていたが、
fs.spectrum は最初から在った(dsp の 1-D 層)。無かったのは 「台帳(fs.ledger)に出ていること」と「op ごとのノート」だけで、 この PoC は 1 つの層しか引かずに「無い」と決め、numpy の rfft を 自前で書いていた。ops1d を台帳へ繋いだのでいまは両方から引ける。
examples/poc_mesh_quality_repair.py
- L602 — ★飽和させて見せる。素の差は最大 %.2f mm で、そのまま塗ると 99 %% の画素が 0 の真っ黒になり「走ったが何も出ていない」図になる。
- L816 — ★両対数で描く。線形軸だと誤差が粗い側の 1 点に潰れて、傾き(=誤差則)が まったく読めない図になる(2026-09-07 に一度そう描いた)。
- L832 — ★累積分布をそのまま重ねると 4 本とも 0.9 以上で潰れて何も読めない。 動いているのは上の裾なので、分位点 0.5〜0.99 を横軸にして 「その分位点の曲率」を縦に描く(逆累積の上半分)。
- L568 — ★実測はそれより遅い。マスク上で実際に消えている粒界画素の割合 f_eff は f より 小さい(ぼけが隙間の両端 1 px に隣の黒を漏らし、局所しきい値がそれを拾う)ので、 f_eff で引き直した予測 ΔG0 + 6.64 log10(1-f_eff) と突き合わせる。
examples/poc_multibeam_bathymetry.py
- L518 — エコーを合成する部分角の本数。★これを 61 にすると、70 度では隣り合う 部分角の到来時間が 330 µs 離れ、パルス幅 64 µs より広くなるので、包絡線が 櫛になって振幅検出が歯を 1 本拾う(検出のずれが -1131 µs と出た)。 到来時間の密度をヒストグラムで作り、パルスで畳むほうが正しい。
- L546 — ★下限を 0 でクリップしない —— 直下ビームは片側だけになり、照らす帯が 半分になってしまう(フットプリントが半分に出る形で 1 度踏んだ)。
- L703 — ★横軸をそのビーム自身のエコー長で割る。生の µs で重ねると 70 度(21 ms)が軸を独占して、直下と 45 度が縦線 1 本になる。
- L706 — ★
plot_series は xlim の外の点を拒否する(枠に貼り付いて 本物のデータに見えるから)。切るのは呼び手の仕事なので先に切る。
- L1125 — ★重なりの真ん中を見てはいけない —— そこは両測線とも同じ振れ角なので、 誤差が同じだけ乗って差がゼロになる。帯全体で最大を取る。
- L1196 — ★縦軸は高さ(= −深さ)にする。深さのまま描くと上下が逆さになり、 「笑っている」形が「しかめ面」に見えてしまう。
- L1267 — ★縦軸は −深さ。深さのまま描くと海面が下、海底が上の逆さ図になる。
- L1301 — ★
op_find は語幹の部分一致で拾うので、件数が 0 でなくても中身は 無関係なことがある(“footprint” → sk_median_disk)。最上位の 名前まで見てから「無い」と言う。
- L1428 — ★全経路の崖は予測より手前。差は振幅検出の偏り(閉形式に無い量)
examples/poc_nuclei_ploidy.py
- L686 — ★逆向きの 2 つの失敗が打ち消して「真値ぴったり」に化ける行が実在する
examples/poc_pallet_load_utilization.py
- L232 — ★デッキの点は雑音で +3σ まで浮くので、床のしきい値で切る。これを 入れないと、はみ出しゼロの荷にも 0.006 m3 の「はみ出し」が出る。
- L479 — ★g = w ちょうどは「格子が偶然そろうかどうか」の勝負になる。
examples/poc_panorama_drift.py
- L108 — ★ 穴 (a): 以下 4 つはどれも fs ファサードにも fs.op にも出ていない
examples/poc_particle_sizing.py
- L213 — ★種を 1 本だけにすると、この曲線の上下はただの揺らぎになる。 4 本の種で平均と散らばりを分けてから「横切った」と言う。
- L428 — ★対照群 —— 融合も縁切れもしていない塊だけを、その塊が写している 粒子そのものと 1 対 1 で突き合わせる。真値の側を全粒子にすると 「大きい粒子ほど融合しやすい」という選び方の偏りが混ざって、 標本化の偏りと区別がつかなくなる(最初そう書いて取り違えた)。
examples/poc_particle_tracking.py
- L702 — ★返りはマスクではなく (N, 3) の (z, y, x) 座標(2-D の
local_max / sk_local_maxima は画像を返すので族の中で不揃い。 10 節の穴 (g))。最初 count_nonzero で数えて桁を間違えた。
- L777 — ★上へ 3.4 倍・下へ 0.93 倍を 1 枚に収めるので、縦軸は log10 の比。 0 が「真値ちょうど」。線形のままだと下向きの外れが潰れて見えない。
- L792 — ★生の MSD を重ねると 4Dτ の直線が全部を支配して差が見えない。 真値で割った比にすると、1.0 からの離れ方(= 壊れ方)が形で読める。
examples/poc_photoelasticity.py
- L160 — ★所見を固定する: これは fullseye の Mueller op に対する厳密な検算で、 δ を 15 度刻みで一周・θ を 5 通り振っても機械精度で一致する(実測 2.2e-16)。 ここが緩んだら 3 節以降で測っているのは「読み取り手順」ではなく op のバグ。
- L181 — ★応力場そのものの検算も固定する。積分した力が荷重に一致しなければ 「真値」ではないし、中心値は閉形式 8P/(πDh) と代数的に同じはず。
- L207 — ★ゼロ点の水準を固定する。以降の「◯倍」はすべてこの 1.09 MPa を分母にしている ので、ここが動くと比較の意味が変わる。
- L231 — ★所見を固定する: 暗視野 1 枚から整数の縞だけ読む素朴な手順は、ゼロ点に 2 倍も勝てない。分解能が fσ/h = 1.78 MPa の刻みに律速されるため。 4 節の位相シフト(誤差が機械精度まで落ちる)との対比がこの PoC の骨格。
- L286 — ★雑音ゼロで同じ強度式から解き戻しているので、θ は厳密に戻るはず (4 枚の平面偏光から 4θ を出す代数がそのまま逆写像になっている)。
- L308 — ★所見を固定する。 (1) 一致率は 95 % を超えるが、100 % にはならない。残りは (δ,θ) ↔ (-δ,θ+90°) の二義性で符号が反転した画素で、1 波長 1 回の測定では原理的に消せない。 「ほぼ合う」でも「完全に合う」でもない、という所見をそのまま固定する。
- L371 — ★所見を固定する。 (1) 減偏光は無い(Stokes の大きさが厳密に 1)。変調が落ちるのは光量ではなく 位相の感度のほうだ、という 5 節の主張の根拠。
- L377 — (2) ★★実測は「マスクを渡すと直る」という素朴な期待の逆を言っている: マスク無し 97.0 % / 標本化不足を外して 97.1 % / 低変調まで外すと 81.9 %。 低変調の画素を抜くと領域が分断され、skimage の unwrap が島ごとに 別の 2π オフセットを選ぶため。「どちらもマスクで外せる」は 予報としては正しいが、処方としては誤り。実測のほうを固定しておく。
- L442 — ★所見を固定する。 (1) 雑音も量子化も無ければ、明視野/暗視野の比から δ は厳密に戻る。
- L445 — (2) ★8 bit 量子化「だけ」の誤差が、雑音 σ=0.002 だけの誤差と同オーダー (実測 0.00277 vs 0.00305)。カメラの bit 深さは雑音と同じ重さで効く。
examples/poc_pigment_unmixing.py
- L860 — ★「1 つの数字にまとめない」の根拠そのもの。同じ行の中で 1.000 と 0.013 が並ぶ。
- L1082 — ★勝てなかったことを図でも残す。ゼロ点の線より下に来ている復元が 1 本も無い。
examples/poc_pipe_wall_loss.py
- L423 — ★健全部は「欠陥が 1 つも掛からない z」を選ぶこと。最初 z=20..60 を 健全部と書いたが、そこは管底腐食の真上だった(肉厚 4.5 mm)。
- L471 — ★r_in/r_out は 画素(ボクセル)単位。mm のまま渡すと視野の外を サンプルして返り値が全部 0 になる(黙って。最初これで真っ黒な図が出た)。
- L817 — ★パネルごとに正規化されるので、同じ範囲に切ってから渡す (切らないと E0 だけ ±4 mm、他は ±1 mm で塗られて比べられない)。
- L1040 — ★穴が塞がったら鳴る。2026-09-07 に鳴り、この節を書き換えた —— 「mm のまま渡すと 例外なしに全部 0 が返る」という指摘を受けて、輪が視野の外なら fail-closed に なった。空を返して黙る側から、拒否して教える側へ変わったことを記録する。
examples/poc_print_registration.py
- L151 — 網点の線数 lpi。★わざと整数比を避けている: 1200/150 = 8.00 px にすると全部の網点が同じ小数位置に落ち、標本化の 位相が揃って合成器に人工物が出る(実測で重心が小数ずれごとに 1.4 px 跳ねた)。 実際のスキャンでも解像度が線数の整数倍になることはまずない。
- L405 — ★ 台帳の口は宣言 out 型に合わせて info を捨てるので
.raw を使う (fullseye/init.py のコメントに実測つきで書いてある落とし穴)。
- L855 — ★ FM 側は探索範囲を 絞らない(絞っても結果は変わらないが、 「AM の折り返しは探索範囲のせいだ」という言い逃れを塞ぐため)。
- L1242 — ★二段が壊れた点は、必ず粗がセルの半径を超えた点(包含関係を固定する)
- L1277 — ★2026-09-13: ‘lattice’ だけ例外を 1 つ許す。flyvision 族の
fly_hex_lattice(複眼の六角格子)が この語を含んで CI で鳴った(run 34751219513)。あれは網点の格子ではないので印刷の穴は 残ったまま —— 例外は名指しで 1 件に限り、それ以外が現れたら今までどおり鳴る。 「語で引く穴の固定」は、無関係の族が同じ語を使った瞬間に偽陽性になる、という実例。
- L1316 — ★ 基準にも雑音を入れる —— 雑音ゼロの像だと star_detect が 「星 0 個」で ValueError になる(それはそれで正しい fail-closed)。
- L1339 — ★2026-09-08: この PoC の指摘を受けて op 側を直した。docstring に 「繰り返し構造には使えない」を測った数字つきで書き、投票の 2 番手の山 / 1 番手 を
vote_margin として返すようにした。 賛成率では区別できない 2 つを、この数なら区別できる。
examples/poc_print_warpage_risk.py
- L364 — ★生まれた層は「そのとき既に反っている面の上」に置かれる(要素誕生は 変形後の配置で行う)。ここを初期化し忘れると、後から生えた層だけ 変位ゼロのまま残り、列平均で測った反りが 1/4 になる (2026-09-07 に踏んだ)。力学(K と f)は公称格子上なので不変。
- L808 — ★首が丸ごと消える。部品が 2 つに分かれるので解いてはいけない。
examples/poc_pv_thermal_survey.py
- L381 — ★MOD_SHELTER は健全なのに風が当たらないモジュール。3 節でこれが 全体平均基準では「故障」に化ける。
- L482 — ★モジュール番号は番号ごとに面積比で決める。番号の平均を丸めると 境界の画素が隣の番号(や 0)に化け、モジュールごとの処理が壊れる。
- L711 — ★モジュール中央値の代償 —— モジュール丸ごとの異常に盲目
- L1169 — ★
apply_cmap は vmin/vmax を渡さないとその配列の min/maxで 正規化する(条件ごとに色の意味が変わってしまう)ので必ず渡す。
examples/poc_real_coin_metrology.py
- L136 — ★数が合っていても、同じものを数えているとは限らない。円 1 個が成分 1 個に きっちり収まるか(1 対 1)を確かめる —— これをやらないと「24 = 24」は 偶然でも成立する(2 枚くっついた塊 1 個 + ごみ 1 個、でも 24)。
examples/poc_real_deblur_honesty.py
- L199 — ★守るのは「どれが勝つか」ではなく勝者が物差しごとに違うこと。 手法名を固定すると、実装が良くなっただけで落ちる門になる。
examples/poc_real_defect_floor.py
- L156 — 振幅の刻み。★これ自体がノブ。粗いと限界が同じ格子点に丸まって、 「σ が大きいほど差が開く」のような刻みが作った差を本物と誤読する (2026-09-09、34 段では σ=1.5 と σ=3.0 の中央値がどちらも 3.20 に丸まった)。
examples/poc_recycling_sorting.py
- L520 — ★掃引の前に、代数から予測を立てて印字する。
examples/poc_registration_basin.py
- L656 — ★利用者が「法線なら在るじゃないか」と
estimate_normals を明示的に渡した場合。 ここが穴の残りで、既定より 14 桁悪い。
- L836 — ★2026-09-06 に穴 1 が塞がった。この assert は塞がった状態を固定する 側へ書き換えてある(以前は
d_fixed < 1e-6 < d_default = 壊れている ことを固定していた)。壊れ方が戻ってきたらここが落ちる。
- L847 — ★2026-09-06 に穴 2 が塞がった。以前は
< 0.9 * len(ka)(壊れていることを 固定)だった。いまは既定のままで完全一致することを固定する。
examples/poc_rotation_invariance_audit.py
- L115 — ★HALCON 流の領域モーメント不変量。3-D 点群用の
moment_invariants とは 別物(名前だけで選ぶと (N,3) を要求されて落ちる)。
- L208 — ★相対ばらつきは分母がほぼ 0 だと意味を失う。Hu[1] は円に近い形では 真値がほぼ 0 なので、ここを黙って % で語ると「30 % ずれた」に化ける。
- L220 — ★予測が外れたところ。書いた時点では「灰を補間して二値化し直すほうが荒れる」と 思っていたが、周囲長まわりは逆だった。
- L262 — ★地がモノクロなので、輪郭は彩度のある色で描く。灰色には彩度が 無いので、彩度のある色はどの階調とも色相で区別がつく ―― 反転色より 確実で、しかも「これは重ねた線だ」と一目で判る。反転色が本領を 発揮するのは、地がカラーで「どの色を選んでも衝突しうる」とき。
examples/poc_safety_clearance.py
- L114 — ★胴はカプセル 2 本を並べて作る。1 本の円柱にすると断面が円になり、 肩(体幹中心から ±0.19 m)が胴の影から外れてしまう —— 実際の胴は幅 0.50 m / 奥行き 0.30 m の扁平な断面で、伸ばした腕は背後から見ると胴に隠れる。
- L126 — ★X0 と速度は「どの試行でも真の分離距離が正のまま(接触しない)」かつ 「危険な帯に十分な時間とどまる」ように選んである —— 速く歩かせると 危険な帯を数フレームで通り抜けてしまい、見落としを数える標本が足りない。
- L673 — ★遮蔽を入れたまま密度を振ると、遮蔽の偏り(+0.12 m)が全部の行に乗って 密度の効きが見えなくなる。要因を 1 つずつ止めるのが対照群の役目。
- L683 — ★雑音と間引きの引きが 1 回だと見落とし率が数 % 上下する。3 回まわして平均。
- L840 — ★行ごとにまとめて評価する(1 セルずつの Python ループだと 15000 回まわる)。
- L1079 — ★ボリューム op は (depth,row,col)。grid_coords は (nx,ny,nz) なので転置する。
examples/poc_scan_to_bim_asbuilt.py
- L658 — ★trim を掛けると「よく合う点だけ」を選び続けて RMSE 0.13 mm の別解へ落ちる (実測: trim=0.9 で吸う角が 0.17 mrad、trim なしで 0.62 mrad)。 as-built 検査では欠陥そのものが大きい残差なので、trim は欠陥を捨てる。
- L950 — ★見出しの主張を 1 枚に: 無傷の天井が、合わせ方だけで傾いて見える
examples/poc_sea_ice_concentration.py
- L232 — 2. ★ゼロ点 vs 線形混合分解 # ————————————————————————— #
- L252 — 3. ★★塊の大きさ(周長)が偏りを決める # ————————————————————————— #
- L291 — 4. ★★密接度で偏りの符号が反転する(打ち消し点) # ————————————————————————— #
- L353 — 6. ★端成分が 5 % ずれたとき # ————————————————————————— #
- L380 — 7. ★★第 3 成分(薄氷) # ————————————————————————— #
- L490 — (b) spec_unmix は在った(★「無い」と書く前に 3 層引いた)
examples/poc_search_sweep_width.py
- L829 — ★形の効き方は捜索の型で違う。走査幅を揃えて、曲線の形だけを比べる。
- L869 — ★取りこぼし 1-P で描く。P そのものだと右上に貼りつき、凡例の箱に 隠れて見えない(実際に 1 度隠して気づいた)。図は「読めるか」を 見てから決める —— 数字が合っていても、隠れていれば伝わらない。
- L1089 — ★再現性の検査: §3 とは種もフレーム数も別なので、同じ条件でどれだけ動くか。
- L1266 — ★ゼロ点を上回っていること(誤検出率を揃えた上で)。倍率は控えめ —— 「ゼロ点でも 174 m 出る」ほうがこの節の所見なので、そこを固定する。
- L1272 — ★外した予測: 全体の背景を引くのはアフィン変換なので、ゼロ点と実質同じ
- L1286 — ★外した予測: 実測の p では平行捜索が C=1 で 1.000 に届かない
- L1290 — ★形は平行捜索にだけ効く: 走査幅を揃えると、ランダムは一致し平行は割れる
- L1293 — ★外した予測: 平らな曲線のほうが強いはずが、逆に弱かった(裾が長いため)
- L1296 — (6) ★W 2 倍 と t 2 倍 は等価
- L1304 — (8) ★見張り役: 誤検出は直下に集中する。閾値だけで W が大きく動く
- L1322 — ★穴を埋めた側の門(2026-09-08)。op_find に和文の段を足し、star_detect の docstring に分野中立の説明語を書いたので、和文で上位に出ることを 固定する。退行するとここが鳴る。
- L1327 — ★「点 検出」だけは今も出ない —— 「点」1 文字は cv_canny / frei_amp のような 輪郭 op の説明にも必ず出るので、同点が並んで押し出される。和文の段が 拾えるのは「2 文字以上の語が効く」場合だけ、という限界を隠さない。
examples/poc_solar_el_inspection.py
- L366 — ★校正線も同じ撮像系(ぼけ)を通す。ぼかさずに貼った校正線は実クラック より 2.4 倍強く応答し、崖が太い側へ寄った(2026-09-07 に踏んだ)。
examples/poc_solar_limb_darkening.py
- L317 — 2. ★ゼロ点(50 % 法)vs 勾配最大 vs 減光モデル # ————————————————————————— #
- L367 — 3. ★★減光係数 u を振る —— 比例ではなく折れ曲がる # ————————————————————————— #
- L391 — ★対照群 —— ぼけを切ると、残るのは幾何(50 % 面の位置)だけ
- L427 — 4. ★★ぼけの効き方はしきい値で符号が変わる(打ち消し点) # ————————————————————————— #
- L488 — 5. ★黒点 —— 3 % の外れ点で半径が動く # ————————————————————————— #
examples/poc_star_astrometry.py
- L264 — 画像の合成(★ 穴: 指定座標に星を置く公開 op が fullseye に無い) # ————————————————————————- #
- L1243 — ★ 「1 回あたり小さい」と「総当たりで小さい」は別の主張。
- L1348 — ★ 「一様・孤立」の偏りが 0.0000 なのは当たり前 —— プレート解を その 24 個で当てたので、最小二乗が残差の平均を 0 にしている。 使わなかった星での誤差を見るには 1 個ずつ抜いて解き直す。
examples/poc_stockpile_volume.py
- L698 — ★物差しで勝者が入れ替わる: 体積は水平底面、重心は平面当てはめ
- L714 — ★外した予測: 補間は過小ではなく過大
- L717 — ★相殺: 補間込みの外周だと誤差が小さく見え、見えた点だけだと戻る
- L726 — ★道具の穴。dem_viewshed が直ったらここが鳴る(それが目的)
- L728 — ★2026-09-08: この PoC の指摘で op を直したので、いまは見えるのが正しい。 自前の視線判定と一致し、閉形式にも近いことを固定する(また壊れたら鳴る)。
examples/poc_strain_history.py
- L507 — ★閉形式の予測。中央 = (w²-1)/24 x d²(速度)/dt²(平滑化のなまり)、 因果 = 遅れ (w-1)/2 ぶん過去の速度を返す。
- L578 — ★履歴そのものを重ねた図は作らない —— 真値・累積・直接が目では 区別できず(誤差は真値の 0.1〜3 %)、「よく合っています」に見えるだけの 図になる。測ったものが見える図だけを出す。
examples/poc_structure_4d_deterioration.py
- L349 — ★遮蔽は設計形状(
p_nom)で判定する。数 mm〜数十 mm の劣化で surface が自己遮蔽の箱の内側に入ると、欠損のいちばん深いところが まるごと欠測になり「深い欠損ほど見えない」という嘘の場面ができる (2026-09-07 に踏んだ: 欠損の谷 -21 mm の core が全部 NaN になった)。
- L437 — ★
fit_plane_3d の法線は符号が任意。真の外向きに合わせる(走査器側)。
- L507 — ★台帳経由は宣言 out 型(pose)しか返さないので
.raw で全部受ける。
- L696 — ★「密度が違うのが悪いなら揃えればよい」を実際に試す(voxel_grid_downsample)
- L1257 — ★観測できる情報量そのものを点群から数える(正規方程式の対角成分)
- L1299 — ★まず測り方そのものの床を取る —— 劣化も姿勢誤差も無しで 2 回測るだけ。
examples/poc_surface_roughness.py
- L272 — ★真値は 帯域を宣言したうえで 定義する。粗さ成分そのものではなく、 「λc で切ったあとの粗さ成分」が真値。ここを生の rough_true にすると、 正しい手順で測っても -23% ずれ、その 23% が標本化の誤差と混ざる。 帯域を含まない「粗さの真値」は存在しない —— これが 2 節の主張でもある。
examples/poc_template_tracking.py
- L93 — ★ 穴 (a): 相関マップを返す公開 op が無いので private を借りる。 第 0 章で公開 op
fs.op.ncc_locate と一致することを検算してから使う。
- L326 — ★ 穴 (d): 公開 op ならここで黙って [0,0,0] が返る。明示的に失敗を返す。
- L1138 — (2) ゼロ点には床がある —— 整数座標の量子化(★ 穴 b)
- L1168 — (9) ★ 主題: 信頼度は条件で得意・不得意が逆転する
- L1172 — ★ 得意な崖が逆である = どちらか一方を信頼度に選ぶことはできない
examples/poc_thermal_radiometry.py
- L507 — ★前向きは直接積分、逆は校正表。同じ表で往復させると誤差 0 が 自明に出てしまい、床を測ったことにならない。
- L528 — ★Case-0 が厳密に 0 なのは 350.0 K がたまたま表の節点に乗るから。 節点を外すと補間の誤差が見える —— 0 を床と呼ぶのは嘘になる。
- L757 — ★横軸は周囲からの上昇。T_obj のままだと発散が左端の 1 本の縦線に 潰れて、肝心の「どこから跳ねるか」が読めない。
- L767 — ★
plot_series は枠外の点を拒否する(枠に貼り付いて本物の データに見えるから)。発散する側は呼び手が先に切る。
- L821 — ★横軸は絶対の Δε。相対 Δε/ε で描くと 3 本が完全に重なる (§2 のとおり式から ε が消えるので)—— 図として何も言わない。
- L1154 — ★guard band に使うのは上側の張り出し。合格と言いたいのは 「真値が閾値より上でない」ことなので、区間の上端で切る。 下側 off[0] を使うと(分布が右に歪んでいる分だけ)浅く切ってしまう —— 1 度そう書いて、誤合格が減らないので気づいた。
- L1257 — ★同じ取り違えでも ε=0.10 の面では L_obj が負に落ちて例外になる。 つまり「止まるか静かに間違うか」は取り違えではなく場面で決まる。
- L1331 — ★発熱部は平らな台にする。山にすると「ボルトと周りが同じ温度」が 成り立たず、見かけの谷が放射率のせいなのか温度のせいなのか分けられない。
- L1378 — ★補正は偏りを消すが、雑音を 1/ε 倍にする。図(d)でボルトだけざらつく理由。
- L1450 — ★
op_find は語幹の部分一致で拾う。blackbody は 4 件返すが中身は cv_blackhat などのモルフォロジで、熱放射とは何の関係も無い。 件数を見て「在る」と読むと外す。先頭の名前まで見てから言う。
- L1600 — 3. ★外した予測: 絶対誤差は高温ほど大きい
- L1602 — ★物差しを変えても、放射率の誤差は上昇比で発散しない(Δε/ε で頭打ち)
- L1605 — ★発散するのは反射見かけ温度のほう(上昇が小さいほど跳ねる)
- L1618 — 6. ★★包含率。床(ρ=0)では RSS も MC も 95 %、相関を入れると RSS が落ちる
- L1622 — ★MC 側は 94.4〜94.6 % に落ち着く(95 % ぴったりではない)。区間の端は 40000 試行の百分位で決めているので標本誤差があり、現実には量子化も 混じっている。そこまで含めて「MC は当たる」と言う。
- L1638 — 7. ★取りこぼしは片側に寄る(対称な ±k·u が歪んだ分布を外す)
- L1642 — 8. ★★guard band: 誤合格は 無視 > RSS > MC、誤不合格はその逆
- L1662 — ★補正は偏りを消す代わりに雑音を 1/ε 倍にする(ε の比 9.5 に近い)
examples/poc_thermography_ndt.py
- L61 — ★観測時間は健全部の t* (6.8 s) より十分長く取る。短いと健全部の膝が 窓の外に出て、TSR が健全部を「窓の端の深さ」と答える(実測で 2.82 mm に張り付いた)。
- L126 — ★ここだけ近似。1 次元解に横拡散は入っていないので、時刻ごとに 拡散長 σ(t)=√(2αt) のガウスで面内をぼかす。物理のスケール則は 正しいが、境界での質量保存までは満たさない。
- L142 — TSR で t* を探す範囲。★端を除くのは飾りではない —— 高次多項式の 2 階微分は 端で必ず暴れる(Runge)。除かないと argmax が最初か最後のフレームに張り付き、 深さが窓端の 2 値に張り付く(実測、2026-09-06)。次数は 4〜11 を掃いて 8 で 決めた(4〜5 では 1.5 mm 以深が端に張り付き、8 以上は 9/11 と同じ答え)。
- L177 — ★格子の刻みで t* を丸めると、深さが階段状に量子化される(64 点だと 5 % 刻み)。 放物線を 3 点に当てて ln t のサブ格子位置まで出す。
- L235 — ★所見を固定する。ここは近似ゼロの検算なので、崩れたら実装が壊れている。
- L249 — ★推定器そのものの偏り。画像を一切通さず、厳密な 1 次元曲線に
tsr_depth を掛ける。ここで出る誤差が「多項式当てはめの床」で、 3 節以降のずれからこれを引いた分だけが横拡散・雑音の寄与。
- L267 — ★所見を固定する: 床はゼロではないが小さい。両側を押さえる —— ゼロになったら「画像を通さない曲線でも数 % ずれる」という 3 節の 読み替え(±5 % は床とほぼ同じ)が成り立たなくなり、大きくなったら 3 節以降のずれを横拡散のせいにできなくなる。
- L302 — ★所見を固定する。この 2 行が同時に成り立つことがこの節の主張そのもの。 (1) 16 個を 1 本の平均にまとめると、TSR は「常に 1.50 mm と答える」ゼロ点に負ける。
- L332 — ★所見を固定する。 (1) 直径が深さの 4 倍以上ある右下三角は数 % で当たる(1 節の床とほぼ同じ)。
- L362 — ★対照群: 横拡散を切った同じ場面。これで「横拡散のせい」と 「画素が足りない/マスクが取れないせい」を分けられる。片方だけ見て 物理のせいにするのが、この種の実験でいちばんよくある間違い。
- L409 — ★対照群の所見を固定する: 横拡散を切ると 16 個すべてが ±8 % に入る。 この 1 行が「壊れている原因は横拡散ただ 1 つで、画素の粗さでもマスクの 取り方でもない」の根拠。緩めると 3 節の結論が『解像度を上げれば直る』 という誤読に戻る。
- L419 — ★上の推論(窓の終わりの拡散長が効く)が正しいなら、窓を切れば直る。 仮説を立てたら、それが外れる形の実験を必ず 1 つ置く。 —————————————————————— #
- L440 — ★この PoC のいちばん重い所見を固定する ——「縦横比の限界」は物理ではなく 当てはめる時間窓の選び方だった。 (1) 窓 4 秒なら小さい 8 個すべてが ±20 % に入る(実測の最悪 -14 %)。
- L528 — ★所見を固定する: 加熱が一様なら生の 1 枚が最多で、TSR の 2 階微分は 1 個も出さない。「深さの推定には効くが検出には向かない」= 同じ道具が 両方に効くとは限らない、というこの節の主張そのもの。
- L575 — ★ランプの映り込み。欠陥と同じスケールの構造を持つのがこちら。
- L602 — ★所見を固定する。 (1) 壊れるのは (c) の欠陥と同じスケールのむらだけ。(b) のなだらかな 傾斜は生の 1 枚をほとんど壊さない —— ここが「予想が外れた」所なので、 (b) が (a) を割り込まないことを明示的に押さえる。
- L683 — ★既定のキューブにも NETD を入れる。雑音ゼロだと健全部の面内ばらつきが 厳密に 0 になり、SNR が 1e9 のような無意味な数になる(実測して直した)。
examples/poc_timelapse_growth.py
- L472 — ★格子の位相を 5 通り振り、偏り(平均)と ばらつき(幅)を分けて数える。
- L610 — 2) ★Y 字 —— 合体する組の中心を通る行で体積を切る
examples/poc_traffic_counting.py
- L256 — ★画面の左右で切れている行は重心が引っ張られる。落とした版も測る。
examples/poc_tree_ring_dendro.py
- L229 — ★画素地図を斜めに読むと境界で番号が k, k+1, k, k+1 と震える(最近傍の階段)。 5 標本(1.25 px)未満の短い走りは直前の値に吸収する —— 放置すると真値の 境界が 1〜2 本増え、「年数が合う方向 18 + 合わない 13 = 31 > 24」になった。
- L336 — ★threshold=0 で全部取り、段の高さは自分で測る。measure_pos の amplitude (勾配ローブの両端差)は木目で勾配が単調でなくなると段の途中で止まり、 0.14 の段を 0.05 と返す(8 節で数える)。
- L345 — ★px へ戻す外縁半径は測った行のもの。扇形 15° 全体の中央値を使うと 偏心成長で外縁が扇形の中で 10 px 以上動くので外側の年輪が全部ずれる (最初そう書いて年輪 18〜35 を丸ごと落とした)。
- L543 — ★年数を間違えた方向でも幅の相関は高いか —— 年数と幅の相関は別の量
examples/poc_vegetation_cover.py
- L320 — ので、ここでは緑・赤の 2 バンドに落として解く。★道具の穴。
- L543 — ★対角線に載っているかどうかが「分数のまま答えられるか」そのもの。 二値手法の線は階段になり、混合画素の帯で対角線から大きく離れる。
- L755 — ★「数字だけ合っている」を絵で見せる。3 枚目と 2 枚目に共通の画素がほぼ無い のに、白い画素の数だけが釣り合っている。
- L953 — (7) ★PPI は雑音で壊れる —— 純画素が 6 割以上あっても葉を拾わない。 一方で雑音ゼロなら同じ場面で当てる = 崖の原因は純画素の不足ではない。
- L993 — (11) ★この PoC が見つけて fullseye 0.1.10 で直した穴。 3 つの大津が同じ入力に違う答えを返していた —— 同じ画像を 4095 倍 しただけで判定が otsu 13.34 pp / cv_otsu 13.92 pp ずれ、sk_otsu だけが アフィン不変だった。原因は
ops._otsu と backends._u8 の np.clip(v, 0, 1)(0..255 の float が全画素飽和して「全部前景」になる)。 いまは 3 つとも倍率で動かない。残っている cv_otsu の 0.5 pp は OpenCV が内部で 8 bit に量子化するためで、これは docstring どおりの挙動。 門は tests/test_value_range_saturation.py。
- L1007 — (12) ★道具の穴:spec_unmix は B=3(色画像)を拒否する = RGB を解く経路が無い
- L1013 — (12b) ★被覆率の数字だけが合っていて画素が 1 つも当たっていない場面が実在する。 この 1 行が「1 つの数字に丸めない」のいちばん強い根拠。
examples/poc_veiling_glare.py
- L229 — ★fullseye 側の突き合わせ: エアリー像 → psf_to_mtf が閉形式と合うか
examples/poc_vessel_network.py
- L263 — ★揺らぎは ぼけたあと に足す。先に足すと PSF が均してしまい、 しきい値の境界はきれいなままになる(最初そう書いていて、 振幅 0.35 まで上げてもヒゲが 1 本も出なかった)。
- L452 — 節 2-3. ★★ヒゲはどこから来るか / 刈るしきい値は解像度に依存する # ————————————————————————— #
- L560 — 節 4. ★★径の推定 —— 分岐の近くで必ず過大 # ————————————————————————— #
- L620 — 節 5. ★★Murray の指数 —— 径の 1 割が指数の 1 になる # ————————————————————————— #
- L751 — 節 6. ★交差の対照群 / 解像度で失われる枝 # ————————————————————————— #
- L890 — (c) ★skeleton_prune3d は「短い枝を刈る」ではなく「全部の枝を短くする」
- L903 — (d) ★fs.skeleton_nodes は docstring が「座標」と言うのに端点しか返さない
examples/poc_warehouse_flow.py
- L145 — ★「人待ち」4 件 x (7.5 + 徐行 2.5) と「通路の干渉」8 件 x (2.5 + 徐行 2.5) は どちらもゼロ点に 40.0 秒を足す —— わざと揃えてある。現実に一致するとは 限らないが、「同じ数字が違う原因から出る」ことは 1 例で示せる。
- L160 — ゼロ点の「止まっている」しきい値 [m/s]。★雑音の作る見かけの速さ (σ√2/Δt = 0.085 m/s @ Δt=0.25 秒)より十分上に置かないと、止まっている人を 動いていると誤判定してゼロ点が減る(0.15 m/s だと Δt=0.25 秒でゼロ点が 半分になり、「細かく撮るほど滞留が減る」という嘘の結論が出た)。
- L239 — ★どちらか 1 台でも見えれば見えるので、死角に入るのは全カメラが遮られる 高さ = 各カメラの限界の最大。ここを min にしていて予測が 0.5 m 外れた。
- L329 — ★並ぶ人の到着時刻は実際に作業が始まる時刻から決める(見積りで 決めたら 20 秒ずれて、待ちの柱が作業の柱と重ならなかった)。
- L342 — ★出会う場所は棚の列の真横でなければならない。棚と棚の間でない交差通路は 両側が開けていて空き幅が 1.9 m あり、「狭い通路」に分類されない(最初の 実装は主通路の高さで出会わせてしまい、10 件中 4 件が「その他」に落ちた)。
- L435 — ★入れ替え(swap)ではなく併合にしてある —— 入れ替えは「同じ柱の中で 遅く始まったほうが待ち」という時間の入れ子を壊さない(役が入れ替わるだけ で、両方の役が正しく埋まる)。壊れるのは 2 人が 1 人に見えたとき。
- L594 — ★止まっている芯だけを残す。柱は 2 人ぶんの足跡で 1.8 m あるので、 通り抜ける人の中心も 2〜3 フレーム柱の中に入る(実測でそれが 「1 人しか居ない干渉」を作り、10 件中 8 件を落とした)。 中央値から :data:
CORE_R 以内に居続けた最長の連なりを芯とする。
- L846 — ★複数人の成分で数えると「通路を 10 人が通った列」が厚くなって混ざるので、 同じ 1 人の中で「待っている間」と「歩いている間」を比べる。
- L1257 — 印の大きさ。★同じ棚前で「補充待ち」と「欠品」が起きるので、大きい印から 描いて小さい印を上に重ねる。同じ大きさで描くと後から描いたほうが前のを 完全に隠し、図の上では 5 件が 2 件に見えた。
examples/poc_water_level.py
- L346 — 2. ★ゼロ点 vs ホモグラフィ # ————————————————————————— #
- L389 — 3. ★アンカーの位置で符号が変わる # ————————————————————————— #
- L422 — 4. ★波立ち —— ロバストが効くのは外れ値があるときだけ # ————————————————————————— #
- L459 — 5. ★★反射 —— 系統的に低く出る # ————————————————————————— #
- L622 — (d) キャリパーは在った(★「無い」と書きかけて 3 層引いて見つけた)
examples/poc_web_roll_periodicity.py
- L123 — ★第1ニップと第2ニップの周長差はわざと 15.7 mm しかない(6 節の崖のため)。
- L158 — 6 節(崖)だけ試行数を上げる。★24 試行では報告率が 12000 mm で 100 %、 14000 mm で 88 % という非単調が出て、「検出の崖」の位置が小標本の揺らぎで 動いた(120 試行では 12000 mm が 93 % に落ち着き、100 % を保つのは 17000 mm 以上)。 崖の位置を主張する節だけは、床が揺れない試行数で測る。
- L253 — ★op は頂点を丸めずに返す(±0.5 を超えたら「そこは極大でない」という 情報)。この PoC は櫛の高調波ビンも評価するので、ここで明示的に丸める。
- L802 — ★床は 0 ではない。24 試行では最長 2 点が偶然 0 % になり「0 % を保つ最短の L」 という判定が通ってしまったが、120 試行では最長 20000 mm でも 2 % 残る。 床を先に測ってから、床の何倍で崖と呼ぶかを決める(0 % は判定に使わない)。
- L1057 — ★120 試行にしたら 100 % ちょうどではなくなった(97 / 98 %)。 24 試行の「100 %」は分母が小さかっただけ。床を見て 95 % に置く。
examples/poc_weld_bead_scan_angle.py
- L485 — ★候補は「母材面の高さに戻った点」なので、溝の外の平らな母材も 全部候補になる。内側 CHECK_IN mm に溶接金属(母材面から CHECK_DEV 以上の落ち込み)が在ることを確かめて初めてつま先と認める —— この門が無いと候補が母材へ滑り落ちて脚長が 1.7 mm 外へ飛ぶ。
- L489 — ★門の深さはいちばん深い溝より深く取ること。最初 -0.6 mm に したら、深さ 0.45 mm(垂直では 0.74 mm)の溝が門を通ってしまい、 16 断面のうち 1 本で 2.2 mm 外れた。
- L572 — ★生き残った断面だけの真値の平均。集計から何が抜けたかを見る。
- L999 — ★凸みだけ予測から外れた。原因はつま先の這い(τ が絶対値のしきい値だから)。
- L1193 — ★溝が角度とともに消えていく様子(母材面からの落ち込みで見る)
examples/profile_shape_inspection.py
- L25 — ★repo 直下のモジュール(profileops)を import するので、チェックアウトから そのまま走らせても通るように repo 直下を先頭に置く。他の例と同じ作法。 これが無いと
py -3.11 examples/<name>.py が ModuleNotFoundError で落ちる (2026-09-09 実測: 走らせる門が無かった 83 本のうち、落ちたのはこの型の 2 本だけ)。
examples/representation_roundtrip.py
- L175 — (c) ガウシアン -> voxel の質量。★一度間違えた数字
examples/shape2d_morph_descriptor_tour.py
- L64 — ★EXTEND: 自分の輪郭抽出結果(
{"shape": (H,W), "cs": [ (N,2) (row,col), ... ]})に差し替える
examples/shapestat_landmark_tour.py
- L71 — ★EXTEND: 自分のランドマーク (N,3) を s に入れる(点の並びが対応していること)
- L123 — ★EXTEND: 自分の群 (K,N,3) を scrambled に入れる(位置・向き・大きさがばらばらでよい)
- L221 — ★EXTEND: 自分のランドマークを「左を全部、次に右を同じ順で」並べて lm に入れる
- L276 — ★EXTEND: surf を自分の面の点(メッシュ頂点・点群)、normals をその向き付き法線にする
- L299 — ★EXTEND: 自分の群 (K,N,3) に差し替える(点の並びが個体間で対応していること)
examples/voxel_labels_color.py
- L81 — 1) ★色の安定性 —— この族の存在理由 # —————————————————————— #
- L152 — 4) ★異方 spacing # —————————————————————— #
examples_3d/alpha_shape_topology.py
- L149 — ★判別的アサート: alpha shape は穴を保つ=軸プローブをほぼ内包しない。 null 手法(凸包)は内包率 ≈1 でこの条件に FAIL する(=判別的)。
examples_3d/ct_hand_radiograph.py
- L34 — 実際に呼んで確かめる。★2026-09-05 まで、この例は「azimuth=elevation=0 なら np.sum(axis=0) と一致」と書きながら一度も確かめていなかった。しかも op → example の索引が hasattr の文字列を呼び出しと誤認していたため、 「例が 1 つも無い op」が 100% カバレッジの中に隠れていた。
examples_3d/geometry_metrology.py
- L186 — ★無限直線版との差を数字で出す(同じ 2 線分)
examples_3d/hull_bounds.py
- L237 — — パネル C: ★新規 min_enclosing_sphere(密着)vs 素朴球(過大)—
- L272 — ★(1) 新規 op — min_enclosing_sphere: 既知球で半径復元 + 全点内包 + ほぼ最小 ============================================================
- L296 — ★(2) 新規 op の beat-null — 非対称点群で素朴球より小さく・ほぼ最小・安全側 ============================================================
examples_3d/mesh_props.py
- L404 — ★巻き順を裏返すと体積の符号が反転する = 符号は向きの検査そのもの
examples_3d/metrics_eval.py
- L234 — ★最近傍距離が嘘をつくのは「変化ゼロで測り返しただけ」のとき。同じ斜面を別の 密度・別の位置で取り直すと、最近傍は面に沿って隣の点を掴むので点間隔ぶんの 偽の変化が出る。M3C2 は法線方向に射影するので、その成分は落ちる。 (この PoC を書く前の予想「C2C は法線シフトでも過大に出る」は外れた —— 平行な面を法線方向に動かすだけなら最近傍距離もほぼ真値。嘘が出るのは 面に沿った取り直しのほうだった。)
examples_3d/sdf_csg.py
- L167 — ★罠:
res はスカラでも軸ごとのボクセル数なので、bounds が非等方だと ボクセルは立方体にならない(ここは x,y が 0.125、z が 0.0625)。体積を h**3 で出すとちょうど 2 倍ずれる —— 実際この例で 295.00 と出て 閉形式 148.03 に対し 99 % の誤差になり、下の assert が鳴いた。
examples_3d/space_carving.py
- L117 — ★
carve_look_at を使う(2026-09-08)。look_at と同じ実装だが、 公開層から引ける名前はこちら —— fs.look_at は render3d の gluLookAt 版(4x4・−Z 前方)という別物で、その M[:3,:3], M[:3,3] を渡すと全点がカメラ後方に落ち、例外を出さずに空の hull が返る。
examples_3d/structured_light_scan.py
- L122 — ★ 座標系の落とし穴:
look_at は gluLookAt 規約(カメラは -Z を向き +Y が上)で 姿勢を作るが、render_mesh はその Vc を (x, -y, -z) に直してから K を掛ける (= depth_to_points / K と同じ CV 規約、depth は +Z 前方)。三角測量は CV 規約の 側で閉じているので、姿勢も FLIP を掛けてから合成する。ここを飛ばすと投影機が カメラの背後を向き、深度は「もっともらしい大きさ」のまま全部間違う (最初の実行がまさにそれで、RMSE 78 mm = 零点と見分けがつかなかった)。
fast.py
- L254 — ★uint8 の gaussian は 置かない。
cv2.GaussianBlur の 8U 経路は 8 bit 固定小数 のカーネルを使うので、float64 の core との差が 1.174/255(実測、この module の ゲート画像 6 枚 × PARITY_AB 5 点の最大)になり「1/255 まで一致」を満たさない。 box は 0.494/255、median / モルフォロジは 0.000/255 なのでそちらだけ載せる。 uint8 の高速 gaussian が要るなら「2/255 まで」という別の契約で明示的に足すこと。
- L294 — ★ここに載っているのは全て :func:
parity のゲートを通ったものだけ。 追加するときは「実装 → ゲートを回す → 通ったら載せる」の順を必ず守る。
- L320 — ★
edges_image(HALCON 名としては canny と同じ)は載せない。registry の その名前は backends_auto の skimage canny(本物の hysteresis つき)で、 core の canny とは別のアルゴリズム。不一致率 1.0(実測)。 ── HALCON 名の twin(registry に同一実装で別名登録されている op)────────── accel._TWIN_ALIASES と同じ発想。ゲートは registry のその名前の実装に 対して回すので、実装がずれていれば落ちて載らない。
- L372 — ★「観測した出力が {0,1} だったか」で判定してはいけない —— 連続 op でも定数画像 では出力が全 0 になり、二値と誤判定して基準が勝手に厳しくなる(実装中に踏んだ)。 判定は registry の 宣言された out_sort で行う。
feat_fpfh.py
- L304 — ★2026-09-07: 姿勢の計算は numpy(FPFH も RANSAC も Kabsch も numpy)で、torch は 返り値を包むためだけに使われていた。そのせいで torch を入れない CI(py3.10 / 3.12)ではこの op が丸ごと ImportError になり、PoC が落ちていた。torch があれば これまでどおり Tensor を返し、無ければ同じ値の numpy を返す(値は不変)。
flyvision.py
- L187 — ★ The cap is on the product, not on either factor, because the accident it prevents is the cross term: a modest 900-ommatidium eye and a modest 512x512 image are each unremarkable and together are 236M float64 = 1.9 GB.
fscript.py
- L1269 — ★2026-09-14: ここは
FsTypeError だけを捕まえていた。逆さの区間と未知の feature を契約どおり FsValueError(= FS_E_INVALID_ARG)にした結果、 fscript の利用者には Python の生の例外が漏れるようになっていた —— 例外の種類を増やしたら、それを言語境界で受けている場所を必ず一掃する ([[feedback_same_bug_class_recurs_check_siblings]])。
fslib.py
- L559 — ★2026-09-14: ここは長らく borderType 既定 =
BORDER_REFLECT_101 (d c b | a b c d — 境界の画素を重複させない折り返し)だった。numpy backend の ndi.gaussian_filter の既定は mode='reflect' = d c b a | a b c d (境界の上で折り返す)で、同じ「reflect」という語が別物を指す。 実測(512x512, sigma=1.0, 乱数): 内部は 4.6e-08 まで一致するのに、端の画素だけ 最大 0.13 = 値域の 13% ずれていた。内部しか見ない検査では原理的に出ない。 connection の 4/8 連結と同じクラスの欠陥(兄弟コードを一掃した 2 件目)。 契約は numpy 側(既存の進化レシピのオラクル)に合わせて BORDER_REFLECT。
- L615 — ★2026-09-14: ここは長らく
ndi.label(mask) = 4 連結の既定だった。 cv2 backend は connectedComponentsWithStats(..., 8, ...) で 8 連結なので、 同じ op が backend によって違う物体数を返していた —— 8x8 の市松模様で numpy 32 個 / cv2 1 個。レシピの答えが「どちらの backend が選ばれたか」で 変わるという、いちばん静かな壊れ方。C ABI を Rust で 2 度目に実装して 突き合わせたときに見つかった(fullseye_abi.h の fs_connection に 8 連結と明記した)。回帰は tests/test_fslib.py が backend 横断で見る。
- L630 — ★2026-09-14: ここは
(mask, 8, cv2.CV_32S) と位置引数で書いてあった。 読むと「8 連結を明示している」ように見えるが、cv2 5.0.0 で実測すると connectedComponentsWithStats(a, 4, CV_32S) も (a, 8, CV_32S) も同じ答え を返す —— 位置引数は connectivity として解釈されておらず、既定の 8 に たまたま一致していただけ。既定が変われば黙って 4 連結になる。 コードが主張している意図を API が守っていない形なので、キーワードで固定する。 (差分ファジングの変異解析で 4 連結を注入したのに一切検出されず、掘ったら 注入のほうが効いていなかった、という経路で見つかった。)
- L723 — ★契約 R-1(fullseye_abi.h): 失敗した演算子は「何も見つからなかった」演算子と 区別できなければならない。逆さの区間は呼び手の間違いであって、「空を寄こせ」 という正当な指定ではない —— 黙って空の Region を返すと、しきい値の計算を 間違えたレシピが「不良ゼロ」として通る。2026-09-14、同じ契約の Rust 実装が FS_E_INVALID_ARG を返すのにこちらは空を返す、という差分で見つかった。
- L743 — ★契約 R-1:
threshold で直したのと同じ欠陥が兄弟に残っていた。逆さの区間は 呼び手の間違いであって「空を寄こせ」という指定ではない —— 黙って 0 個を返すと、 面積の下限と上限を取り違えたレシピが「該当なし = 良品」として通る。 2026-09-14、Rust 実装が FS_E_INVALID_ARG を返すのにこちらは 0 個を返す差分で発見。
fsruntime.py
- L284 — ★判定レシピは、あらゆるプロファイル(産業用に限らない)で、厳選された fslib 由来の builtin のみを使える。それ以外の呼び出しは
fscript._call_registry_op → api.RT を通して解決される 650 op の進化レジストリ op であり、その _safe wrapper は fail-OPEN(op の失敗を握り潰して無害な「欠陥なし」の値を返す)。この面はレシピの演算子であってはならない —— studio / リファレンスのランタイムも部品を判定するため —— ので、それを使うレシピはロード時に拒否する(docs/FSCRIPT_DECISION.md 1.6b)。
fullseye/__init__.py
- L531 — ★ 宣言 out 型に合わせる adapter は、タプルを返す op の2 番目以降を 捨てる(
drizzle_resample の wht、piv_cross_correlate の info)。捨てられた側が必要なとき、台帳の入口からは届かなかった。 2026-09-06、超解像の PoC が flow, info = fs.ledger.piv_cross_correlate(...) と書いて (2,R,C) を第 1 軸で開き、dy の 2 行目を dx として使い、 ずれ推定を 0.12 → 0.74 画素にした(例外は出ない)。 .raw で素の返りに届く: fs.ledger.piv_cross_correlate.raw(a, b)。
fullseye/mcp/catalog.py
- L104 — ★5 層。最初は 4 層で組み、「索引にもレジストリにも facade にも無いノート」が 480 枚残った。残骸かと思ったら 480 / 480 が
fullseye.ledger で解決した (型付き台帳。レジストリでは tb_project、台帳では project のように接頭辞が 違う)。「無い」と言う前に全層を引く —— 4 層目まで引いて止めていたら、実在する 480 個の機能を残骸と呼んでいた。
- L318 — ★同点の割り方は
api.find_op と同じにする: 別名を複数 op が共有するとき name == halcon の正典を先に。次に層が多い(実行もノートもある)方。 実測 2026-09-15: “gauss” で gauss_filter(正典)と gaussian が同点になり、 名前順だと _ < i で前者が先に来た —— 偶然そうなっていたのを規則にした。
fullseye/mcp/diagnose.py
- L87 — ★順序が答えを変える(2026-09-15 実測):
ones + inf は有限部の std が 0 なので 「定数」が先に当たり、0..715 の配列は 99.9 % が ≥ 1 なので「飽和」が先に当たった。 より根本的な異常を先に言う: 非有限 → 定数 → 範囲外 → 飽和 → 平坦。
- L106 — ★飽和・平坦は image / color だけ。region は 0/1 が契約なので「飽和」ではない —— リファクタで region を含めてしまい、
--demo で otsu の出力が「飽和」と判定されて 小図が昇格した(2026-09-15 実測)。region の定数(空 / 全面)は上で拾う。
fullseye/mcp/handles.py
- L47 — ★thumb_dir を渡されたときに作っていなかった(mkdtemp のときだけ存在する)。 小図の保存が FileNotFoundError で落ち、テスト 4 件で発覚(2026-09-15)。
g1_policy_bridge.py
- L33 — ★配布物にローカル絶対パスを焼き込まない(2026-09-05 の監査で、非公開の兄弟 プロジェクト名が PyPI の wheel に載っていた)。既定は環境変数で与える。 Unitree G1 のシーン XML。MuJoCo Menagerie の
unitree_g1/scene.xml を指す。
- L61 — ★セキュリティ境界。
pickle は load 中に任意の callable を呼べるので、 find_class を素通しにすると チェックポイントを開いただけでコードが走る。 RL のチェックポイントは他人から貰う前提の成果物なので、これは現実的な脅威。 (2026-09-05 実測: 素通し版は os.system / subprocess.Popen / builtins.eval をそのまま返し、load() 中に実際にファイルを作れた。) ここに載っているのは、brax PPO のチェックポイントが実際に参照する数値系だけ。 足りないものが出たらこのリストに足す(例外メッセージがモジュール名を出す)。
honest_summary.py
- L58 — ★機能ゲートに落ちた auto op を看板の数字から除外する —— 以前は [warn] 表示されるだけで数には入っており、ゲートが拒否する op で「機能ゲート済み」の parity 数を水増ししていた。
- L77 — ★2026-09-08: この行はこう書いてあった —— “= %d evolvable registry ops + %d n-ary capability ops (disjoint).” 実測すると 979 + 17 = 979、つまり n-ary の 17 本は
reg_counted の部分集合(nary_names - reg_counted は空)。 見出しの 979 は正しいのに、内訳の行だけが「足し算」に見え、読者が足すと 996 になる。数字が合っていても説明が嘘をつく形なので直した。 内訳が和として成り立つかは tests/test_honest_summary_arithmetic.py が毎回見る。
imgevolve.py
- L50 — ★握り潰さない(2026-09-06 の敵対的レビュー)。
imgops_nary は numpy と scipy しか要らない一次モジュールなので、import に失敗するのは「壊れた checkout」であって「その環境には無い機能」ではない。以前は except Exception: pass で、この関数が生成器と検査の両方を兼ねている ため、17 op が丸ごと消えた索引を CI が緑のまま公開できた。
imgio.py
- L99 — ★判定は 2 つ(2026-09-08、同日中に直した)。最初は「CIE L* の折返しが 0 回」 だけで選んでいたが、
poc_colormap_readability が cividis は折返し 0 回 なのに色差の尾根を立てることを実測した。明度が単調でも、色差の刻みが不均一なら なめらかな場に無い境目が見える —— 片側の基準で「安全」と名乗っていた。 実測(512 段、隣接色差の max / median と、中央値の 1.6 倍を超える局所最大の数): ========== ========== ============== ========== マップ L* 折返し ΔE max/median 尾根の本数 ========== ========== ============== ========== gray 0 1.33 0 viridis 0 1.38 0 plasma 0 1.38 0 magma 0 1.48 0 inferno 0 1.50 0 cividis 0 2.23 1 turbo 1 1.78 1 ========== ========== ============== ========== cividis を外したのはこの repo の近似 LUT が粗いからで、公開されている cividis そのものの問題ではない(制御点 6 個は逐次マップの中で最少)。 色覚特性への配慮で選びたい向きには :data:CVD_SAFE を用意した。 tests/test_pseudocolour_family.py が両方の基準を毎回測る。
- L124 — 色覚特性(P/D 型)でも順序が読めるとされるマップ。★
cividis の近似 LUT は 制御点が 6 個で色差の刻みが粗く、:data:PERCEPTUAL_SAFE の基準は満たさない (実測 ΔE max/median 2.23)。制御点を増やせば両方に入れられる —— 一次情報の値を手で写すと誤記の前科があるので、出典を確認できるまで保留。
matappear.py
- L167 — ★ 0 次元(スカラ)を渡すと
r.shape[-1] が素の IndexError を投げていた (2026-09-04 の敵対的監査で摘発)。分光反射率は最低でも波長軸を持つ ―― スカラは「波長ごとの値」ではないので、番人で明示的に断る。
- L296 — ★ 実際の格子は両側に回折する(溝が対称なら ±m の効率はほぼ同じ)。ここで ±両方を入れないと、光源と視線の位置関係によっては解が全部負になり、 「正の λ だけ残す」フィルタが全部落として真っ黒になる。実測: 溝に直交して 照らした CD(Δsin = −0.55)は m=+1,+2 が λ<0 で全消え、m=−2 の 440 nm が本命だった。
match3d.py
- L297 — ★2026-09-07: numpy の FFT に置き換えた。式は同じ(float32 の fftn → 位相のみ → ifftn の実部 → argmax)で、torch でやる必要がどこにも無かった。torch を入れない CI(py3.10 / 3.12)ではこの op が ImportError になり PoC が落ちていた。
- L1633 — ★2026-09-07: 本体を numpy に書き換えた。この ICP は 最近傍探索が cKDTree、 姿勢の更新が 3x3 の SVD で、torch でやる仕事が 1 つも無いのに torch を 必須にしていた。torch を入れない CI(py3.10 / 3.12)で PoC 4 本が
ImportError: this operator needs the optional 'torch' backend で落ちて 発覚(手元には torch があるので気づけなかった —— 門は事故の起きる場所に 立てる、の実例)。数値は float64 の同じ式なので環境で結果が変わらない。 返り値の型は互換のため据え置き: torch があれば torch.Tensor、無ければ numpy.ndarray(値は同一)。device に “cpu” 以外を頼まれたら fail-closed。
- L1848 — ★2026-09-07: 本体を numpy に書き換えた。最近傍探索・6x6 の正規方程式・ Rodrigues のどれも CPU の小さい線形代数で、torch でやる必要が無かったのに 必須になっていた。torch を入れない CI(py3.10 / 3.12)で PoC が ImportError で落ちて発覚。式は同じ float64 なので結果は変わらない (torch 版との差は R/t で 0、RMSE で 0 を実測)。
- L2810 — ★2026-09-07: 輪が画像の外にあるなら fail-closed。
r_in/r_out は 画素単位なので、mm のまま渡すと視野の外を読み、例外なしに全部 0 が返る (poc_pipe_wall_loss が真っ黒な図を 1 枚出して発覚)。中心から画像の四隅 までの最大距離より内側の半径が 1 つも無ければ、返るのは空以外にありえない。
- L2821 — ★2026-09-07: grid_sample(bilinear, align_corners=True, zeros padding)を scipy の map_coordinates(order=1, mode=”constant”, cval=0)に置き換えた —— 同じ双線形補間で、torch を入れない CI(py3.10 / 3.12)でも走る。 実測差は最大 6.0e-06(値域 0..1 の乱数画像。float32 と float64 の丸めぶん)。
- L2866 — ★2026-09-07: polar_unwrap と同じ理由で map_coordinates に置き換え(双線形・ 範囲外 0)。torch 不在でも走る。実測差は最大 7.6e-06。
- L3117 — ★2026-09-07: affine_grid + grid_sample(align_corners=False, zeros padding)を numpy の座標計算 + scipy の map_coordinates(order=1)に置き換えた。torch は 双線形の再標本化にしか使われておらず、torch を入れない環境(CI の py3.10 / 3.12)でこの op が ImportError になっていた。規約はそのまま写した: 出力ボクセル (d,h,w) の正規化座標は ((i+0.5)/N)2-1、回転後に (g+1)/2N-0.5 で入力の画素座標へ戻す(align_corners=False の定義)。 grid の最終軸は (x, y, z) = (W, H, D) の順。torch 版との実測差は最大 7.6e-06。
- L624 — ★ここを「もう片端が次数 3 以上」と書いていた最初の版は、実測で 一度も発火しなかった: ヒゲの根元が枝の端点クラスタと 26 近傍で 融合して次数 2 になる配置が普通にあり、その場合に素通りしていた (「刈った」と報告しながら 0 本という、いちばん静かな失敗)。
occupancy.py
- L223 — ★2026-09-07:
res は軸ごとを受けるようにした(長さ 3 も可)。立方限定だと 鳥瞰格子(薄い z × 広い xy)のような扁平な体積で、要らない軸まで同じ刻みを 強いられる(poc_bev_sensor_fusion の実測: 409.6 万ボクセルのうち使うのは 8.1 %)。 同じ族の grid_coords は最初から軸ごとの res を受けていた —— 入口と出口で 契約の広さが違うのを合わせた。スカラを渡す既存の呼び手は不変。
- L317 — ★2026-09-07:
res は軸ごとを受けるようにした(長さ 3 も可)。それまでは int(res) で立方格子だけを許しており、esdf が長さ 3 の異方 voxel_size を 受け付けるのに、その出力を world 座標で引くこちらが立方限定という片側だけ狭い 契約になっていた。CT の薄い接合層 (30,180,180) のような格子でそのまま詰まる (poc_ct_void_morphology で実測)。スカラを渡す既存の呼び手は不変。
opassist.py
- L50 — ★2026-09-08: ops1d(dsp 16 + funct1d 23)は登録済みなのに、docs にも op_run / op_assist / op_find にも出ていなかった —— 「登録した」と 「引ける」は別。opdocs に足したら、この門が引けない側を鳴らした。
- L242 — ★ 設計(2026-09-04、ユーザー「色々なコンテナ型は扱えるほうが良いけど、統一感も 大事です」): 最初は
kind に “seq” や “matrix” を混ぜていた ―― つまり値の型 (数値か整数か選択肢か)と容器の形(1 個かベクトルか行列か)が 1 つの欄で 競合していた。UI から見ると「int の 3 ベクトル」が表現できず、行列だけ構造が seq キーの下にあるなど、扱いがばらける。ここを直交させ、kind は値型だけ、 容器は常に container に入れる形へ統一した。スカラも例外にしない ({"form": "scalar", "shape": ()})ので、UI は分岐を 1 本に書ける。
- L357 — ★ 最長一致。短い順に見ると
sigma_per_mm が _mm に当たって “mm” になる (実際は 1/mm)。単位を間違えると UI の数字が黙って別物になる。
- L454 — ★ ここが要点: 既定値が tuple で与えられていない引数がある。
center=None(省略可の (row,col))、必須の trans(3 ベクトル)、 k_cam(3x3 行列)…… 既定値だけを見ると「数値 1 個」に見えてしまい、 UI が spin box を 1 個出して破綻する。名前で構造を補う。
- L610 — ★ 実測で判明:
prism_min_deviation_deg の波長入力に 0..1 の汎用 signal を渡すと 「波長は正の値」で弾かれ、サンプルが動かない op になっていた。単位が分かる なら、その量として妥当な範囲を種にする方が「押せば動く」に近い。
- L730 — 和文(CJK)の連なり。★
_WORD_RE は [a-z0-9]+ なので、日本語のクエリは 語が 1 つも取れない(_WORD_RE.findall("点 検出") == [])。語幹の段が 死に、部分一致は空白ごと含む文字列を探すので、和文の複数語クエリは構造的に 必ず 0 件だった —— docstring の大半が日本語で、6 言語を配っている製品で。 2026-09-08 に poc_search_sweep_width が踏んで判明(op_find("点 検出") / ("スポット 検出") / ("小さい目標") がいずれも 0 件で、副画素重心つきの 点目標検出は star_detect しか無いのに和文から辿り着けなかった)。
- L783 — 語幹一致とみなす共通接頭辞の長さ。★4 にすると “median”/”medial” や “contrast”/”contour” が繋がってしまい、5 で切ると “correlation”/”correlate”(8)・”segmentation”/”segment”(7)・ “rotation”/”rotate”(5)・”gaussian”/”gauss”(5) は拾えて、上の 2 組は拾わない。
- L793 — 共通接頭辞の後ろに許す語尾。★接頭辞の長さだけで判定すると “median”/”medial” が繋がる(共通 “media” が 5 文字ある)。語尾が 屈折語尾らしいかどうかを見ると、”correlation”/”correlate”(ion / e)は 通り、”median”/”medial”(n / l)と “corner”/”cornea”(r / a)は落ちる。
- L889 — ★床。無い状態だと “zzz-nothing-matches” が
histogram_match を返す (“matches” が match_* に語幹一致するため)。当たった語の重みが クエリ全体の 15 % に満たなければ「当たっていない」とみなす。 実測: “digital image correlation” は 0.19(通す)、 “zzz-nothing-matches” は 0.10(落とす)。
ops.py
- L628 — ★端は端の値で埋める。以前は
np.convolve(x, k, "same") で、 これは両端の w 点をゼロと平均する —— 輪郭の始点と終点が 原点 (0,0) の方向へ最大 50 px 以上引きずられ、輪郭 140 本ぶんの 赤い筋が左上へ収束する図になった(2026-09-06、op ごとの図を初めて 作ったときに発見。数値テストでは平均ずれ 0.3 px で見えなかった)。
- L1498 — ★ネイティブ側が退化入力でプロセスごと落ちる op の台帳(2026-09-05)。
guard は Python の例外しか捕まえられない。C/C++ の中で境界の外へ書き込まれたら そこで終わりで、利用者のパイプラインごと消える —— fail-soft の最悪の破れ方。 入口で弾く以外に手が無いので、理由つきでここに載せて登録時に関門を掛ける。 プラットフォームで挙動が違うのがこの台帳の存在理由。下の 3 本は Linux(Ubuntu 24.04 / Python 3.12 / PyPI の wheel)では落ちるが、 Windows では同じ入力で 1 件も再現しなかった。ネイティブのビルドが違えば 境界の壊れ方も違うということなので、「この種類の入力なら大丈夫」という 細かい線引きは信用できない —— 退化入力はまとめて拒否する。 直したら消す、ではなく上流が直ったことを確認できたら消す(こちらは 自分のコードではないので、消す条件が違う)。
ops3d.py
- L375 — ★ out は image2d ではなく rgbimage(2026-09-02 実測)。docstring も 実装も「RGB (size, size, 3) float [0,1]」で、この行だけが 2-D の 輝度画像を名乗っていた。mesh の種を入れて初めてこの op が実行され、 型述語が「declared ‘image2d’ but returned ndarray(512,512,3)」と TYPEMISS を出して顕在化した(それまでは (V,F) を 2 位置引数に割る 形のせいで一度も実行されていなかった)。他の render_* 3 op (ambient_occlusion / cast_shadow / supersample_mesh)は実測どおり 2-D なので image2d のままでよい ― 嘘だったのはここ 1 行だけ。
- L465 — ★新しい sort は作らない: ノード表と枝表は「単位も意味も違う 2 つの表」で、 タプルで返して adapter に
r[0] と書くと 枝表を黙って捨てる (pose_error / m3c2_distance で繰り返した失敗の型)。1 つの dict に 両方を入れれば宣言 ‘table’ が実返りと一致し、捨てるものが無い。
- L616 — ★2026-09-08 追加。それまで彫刻用の姿勢ヘルパ(visualhull.look_at)は どの公開層からも引けず、同名の render3d.look_at(gluLookAt・−Z 前方)を 掴むと 例外なく空の hull になった(poc_livestock_body_volume)。
- L637 — ★ out は image2d ではなく keypoints(2026-09-15 実測)。実返りは 像面上の (N,2) 画素座標で、入力 (160,3) に対し (160,2) が出る —— 画像ではない。同じ型の嘘を “render” 節の
project_points で 2026-09-02 に既に直しているのに(「旧宣言 ‘image2d’ は型の嘘で、 pnp3d 側の ‘image2d’ 宣言と噛み合って PnP を壊していた」)、 この 1 行だけが兄弟一掃から取り残されていた。 例外にならないのは _sort_ok が image に ndim == 2 しか求めず、 (N,2) が「幅 2 の画像」として黙って通るから。値域も画素座標 (実測 16.0 .. 47.9)で [0,1] ではなく、image を名乗る限り 下流の閾値 op に渡ると意味を失う。
- L727 — ★ 保留していた理由(a)「points 候補リストが短くなり既存 champion を黙って 書き換える」は、backends_typed.TYPE_TO_SORT で coordgrid → points へ畳む ことで消えている: 2-D 橋の tb_sphere_sdf / tb_box_sdf には INPUT_ADAPTERS._points_to_grid が付いていて 点群から座標場を実際に作って いるので、あちらの “points” 宣言は嘘ではない(実測: (64,3) を渡すと (16,16,16) が返る = 生きている)。嘘だったのは 3-D 台帳の側だけだった。
- L882 — ★ axis=1。
pairs の正典は (N,2)(消費側 6 op が (2,N) を名指しで 拒否することを実測)。述語が lambda v: True だった間、ここは (2,n) を 作っており「どの消費側も受け取れない形」を宣言型として名乗っていた
- L920 — ★ position の正典は [z, y, x] の 3 成分。多数決ではなく消費側を実行 して決めた: refine_translation_lk / refine_lm は 4 成分を渡すと “init_pos must have exactly 3 components [z, y, x] (got 4)” で fail-closed する(実測)。生成器も (8.0, 8.0, 8.0) の 3 成分。ところが match_* 系は docstring どおり [score, d, h, w] の 4 成分を返しており、宣言 out が “position” のまま流すと後段の精緻化 op が全滅する = 型の嘘。 score 自体は正直な情報なので関数側は削らず(get() は 4 成分のまま)、 台帳の型を名乗る call() 側で座標だけを取り出す(project_points と同じ扱い)。
opsastrostack.py
- L85 — ★ 代わりに 生の (N,H,W) ndarray を明示的に拒否した。3-D 配列は video (T,H,W) / voxel (D,H,W) / histcube (H,W,T) / zscan のどれもが 同じ構造検査を通り、取り違えても例外にならず「もっともらしく間違った 合成結果」が返る —— photon 族が histcube を voxel から分けたのと まったく同じ危険である。ただしここでは型を増やすのではなく 「list であること」を要求することで同じ防御を得た。list(volume) と 書いた時点で、呼ぶ側が「先頭軸はフレーム軸だ」と宣言したことになる。 * image2d —— 合成結果、drizzle の出力、単一フレーム。どれも 2-D の float64 で、既存の 2-D op(フィルタ・閾値・morphology・psf_to_mtf)が 意味を保ったまま使える。非負でもない(κ-σ 合成の残差やスプライン 補間の負の縁が出る)ので counts を名乗るのは逆に嘘になる。 * keypoints ——
star_detect の返りは (N, 2) の (row, col)。 TYPE_CHECKS の keypoints は「(N,3) または任意の 2-D 配列」なので そのまま該当し、psf_fit / aperture_photometry が食う。
-
L101 — ★ ここは pairs ではない: pairs の正典は reprconv 側の 6 op が決めた 「(x, y) の対」で、こちらは画像座標の (row, col) であり fit_transform / mosaic と同じ規約。混ぜると行と列が入れ替わる (features.match_keypoints が (x,y) を返すのに fit_transform が (row,col) を要求する、というこの repo 既知の罠と同じ形)。 keypoints を名乗れば、少なくとも「画像上の点」という約束は共有される。 * indices —— lucky_select が返す採用フレームの添字(1-D int)。 既存語彙そのもの。[frames[i] for i in idx] で images に戻る。 * measurement —— noise_sigma は実スカラ 1 つ。 * matrix —— frame_align の (3,3) 同次変換。transforms / fit_transform / mosaic が扱っているのと同じ物で、専用語を作る理由が無い。 * table —— dict / list of dict(品質、PSF 当てはめ、測光)。 TYPE_CHECKS の table は list |
dict なのでどちらも該当。 分けなかったことの代償(honest): images プールに天体でない画像列が 入ると、frame_align は星が見つからず ValueError で止まる。これは fail-closed なので「発見ゼロ」ではなく「到達したが正しく拒否した」だが、 連鎖ファザーから見ると align 系 2 op が CONTRACT にしかならない可能性がある。 photon 族が counts を分けた理由(7/17 が一度も実行されない)と同じ症状が 出うるので、もし実測でそうなったら、そのときは「点像を含む画像列」を 別プールにする判断が正当化される —— 先回りして型を増やすことはしない (型は「混ぜると嘘になる」証拠が出てから増やす、が本 repo の順序)。 |
opsdem.py
- L35 — ★ 正直な限界:
depth プールにはカメラの透視投影による深度も入りうる。 透視深度は 1 px が地上で何メートルかが深さとともに変わるので、一定の cell_size を当てた傾斜はもっともらしく間違う。ではなぜ型を 分けないか —— これは型の取り違えではなく cell_size の与え方の 誤りと同じ種類の誤りで、cell_size は既に必須引数(既定値を置か ない)にしてある。型を増やしても正射でない深度は防げず(述語は 「2-D の実数配列」までしか見られない)、代わりに種を持つ op が 1 つも 無い dem プールができて 13 op すべてが永久に未実行になる。 防げないものを型で防いだことにするより、必須引数と docstring で明示し、 ファザーには実際に走らせるほうを採った。 * dem_fill_sinks の出力だけ depth —— 窪地を埋めた結果はまだ 標高格子で、そのまま dem_flow_direction へ入る。ここを image2d と宣言すると族内の連鎖(埋める → 流す)が型で切れる。 * dem_flow_direction は labels —— 返りは int8 の 0-7 と -1(流出先 なし)で、順序に意味が無い符号である。mask を名乗ると二値の ように扱われ、image2d を名乗ると 3 と 4 の平均に意味があることに なってしまう。labels の述語(整数 dtype の 1-3 次元)にそのまま該当。 * dem_stream_network は二値だが image2d —— 中身は 0.0/1.0 に加えて 欠測の nan を持つ float64 で、mask の述語(bool か整数 dtype)を 満たさない。bool にすると「河道でない」と「そもそも値が無い」が 区別できなくなるので、型のほうを実装に合わせた。 * 残りはすべて image2d —— 傾斜[度]・方位[度]・曲率[1/m]・陰影[0,1]・ 起伏[m]・地平線仰角[度]・天空率[0,1]・可視[0/1]。どれも 2-D の実数場で、 既存の 2-D op(平滑化・閾値・morphology・疑似カラー・図注)が意味を 保ったまま使える。値域は [0,1] とは限らないが、それは astrostack の合成結果と同じ立場で、image2d は輝度の約束では なく「2-D の実数場」の約束としてこの repo では使われている。 カテゴリ → [(op 名, module, [入力種別], 出力種別)]
opsflyvision.py
- L62 — ★ 重みは公開しない:
fly_hex_resample の個眼×画素の重み行列は functools.lru_cache で内部にだけ保持し、op の入出力型には現さない —— 出すと「画素座標系に依存する巨大な派生物」が型プールを汚し、下流の 2-D op が それを画像と取り違えて黙って処理してしまう(zscan を video に渡すと通る、と 同じ事故の型)。出さないことでこの取り違えを構造的に不可能にする。
opsimgforensics.py
- L206 — ★
phash の述語で dtype を見ることが本体である。ndim == 1 だけだと 既存の signal と完全に重なり、分けた意味が無くなる。
- L208 — ★
fingerprint の述語は image2d と 形では区別できない。ゼロ平均性で 切るしかなく、それは実行時の統計的な当て推量なので、述語も同じ弱さを持つ (だから型で分けている)。この弱さを述語のコメントに残しておくこと。
- L224 — ★
fingerprint の種は 必ず sensor_fingerprint を通して作ること。 rng.standard_normal((H, W)) を直接置くと、それは指紋ではなく白色雑音で、 照合は常に「無相関」を返す = 検査面が増えたつもりで増えない。
- L227 — ★
images の種は 同じ shape で 2 枚以上。1 枚だと sensor_fingerprint が fail-closed し続けて一度も走らない。
- L242 — ★
jpeg_ghost_quality の qualities=None は「40..95 step 5 の 12 本」を 仮定するので、images の種が 12 本でないと必ず ValueError になる。 これは意図した fail-closed(添字と品質がずれた地図を返さない)なので、 ファザー側で本数を合わせる。
- L246 — ★
watermark_* の bits は容量(LL の 8x8 ブロック数)以下でなければ ならない。64x64 の image2d + level 1 の LL は 32x32 = 16 ブロック。
opsinterferometry.py
- L96 — ★ 既存
signal に相乗りさせなかったのは実測の結果である。最初は 「csi_signal_simulate ([] -> signal) が本物の干渉信号をプールへ注ぐから 到達できる」と判断したが、その配線で連鎖ファザーを回すと 600 連鎖(300x長さ6 + 300x長さ8)で csi_peak_position と chromatic_confocal_height が 1 度も実行されなかった(記録は CONTRACT が 7 件のみ)。原因は signal 種が負値を持つ正弦波で、 入口 op が同じ連鎖で先に引かれる確率が低いこと。opsphoton が counts で 踏んだ罠とまったく同じで、fail-closed が完璧に効いた結果として 「発見ゼロ」が頑健さに見える。sweep を専用プールにした同条件の 再測定では 9 op すべてが実行された。 2 種を混ぜても取り違えが黙って通らないことは、それぞれ専用の判別で 担保してある(どちらも閉形式で測った閾値): - スペクトルを csi_peak_position に渡す → carrier_tolerance。 干渉信号は搬送波が 2/λ(Nyquist の 0.333)に立つが、共焦点ピークは 0.010。実測で 1000 倍の単位誤りも同じ検査が捕まえる。 - 干渉信号を chromatic_confocal_height に渡す → max_carrier_fraction。共焦点応答の AC 成分は低周波だけ(実測 0.010 / 0.010 / 0.015)、干渉信号は 0.333。 入口 = csi_signal_simulate / chromatic_confocal_simulate(どちらも 引数なしで産む)、出口 = csi_envelope (-> signal) と 2 つの measurement op。
opsoptics.py
- L125 — ★ pupil_blur は「画像 × カーネル」の一般畳み込み(filters_freq.convol_fft) ではない —— PSF の標本間隔 λN/oversample を検出器ピッチへ面積積分して から畳む、その単位合わせが本体。だから PSF を作る側に置く。
- L140 — ★ normals(点群の (N,3) 法線)ではなく normalmap。両者は形は似ているが、 (N,3) を渡すと _normal_map が ValueError で弾く。ここを normals と申告すると 「点群の法線を渡してよい」という嘘になり、連鎖ファザーは毎回 CONTRACT で 終わってこの族を一度も実行しない(= 発見ゼロに化ける)。
opsphoton.py
- L85 — ★ なお counts は 1-D の float64 配列そのものなので、dsp / funct1d を「呼ぶ」ことは何も妨げられない(型語彙は連鎖ファザーの pool 分離で あって、Python の呼び出し可能性ではない)。逆向きの橋 = signal を 非負化して counts にする経路は下の「橋」注記を参照。 * countrate — SPAD の計数レート列(Hz)(1-D、非負)。counts と同じ 「非負の 1-D」だが、別の量なので別プールにした。理由は 2 つあり、 どちらも実測に基づく: (a) 単位が 7 桁違う。counts プールの値域は 0-250 カウント程度で、 これを spad_deadtime_apply(dead_time_ns=50) に渡すと 250 Hz x 50 ns = 1.25e-5 → 恒等写像に限りなく近い値が 例外なく返る。op は「到達」しても、デッドタイムの物理(飽和、 1/tau の fail-closed、麻痺型の非単射性)は一度も踏まれない。 これは histcube を voxel に相乗りさせたときと同じ 「もっともらしく間違った通過」で、CONTRACT も TYPEMISS も出ない。 (b) 物理が違う。デッドタイムは検出器のレート流に効くのであって、 TCSPC の時間 bin ヒストグラムに bin ごとに掛かるものではない (ヒストグラムに対する正しい歪みモデルは Coates = tcspc_coates_correct)。同じ語彙にすると、進化探索が 「ヒストグラムにデッドタイム補正を掛ける」という物理的に誤った 連鎖を正当な型接続として学習してしまう。 countrate は apply <-> correct の 2 op しか持たない狭い sortである ことを承知のうえで分けている(jones が 2 op、stokes が 3 op なのと同格)。 ただしこの 2 op は互いに厳密逆なので、プール内で往復不変量が回る。 * histcube — 画素ごとの到達時刻ヒストグラム立方体 (H, W, T)、時間軸が 最後。既存の
voxel は「3-D 配列」で TYPE_CHECKS も ndim == 3 だけ なので構造上は通ってしまう。しかし voxel は (D, H, W) の空間格子で、 軸の意味が違う: (D,H,W) のボリュームを histcube として渡すと dtof_cube_depth は W を時間軸と読み、例外ではなく「もっともらしく 間違った深度マップ」を返す(実測: 一様ボリュームで全画素 0.0075 m)。 なお flat な histcube は dtof_cube_depth 側でも empty 判定して黙って 通さない(二重防御)。 橋(狭い sort への対策、実装は未了 = 親の判断待ち): signal -> counts の橋になりうるのは「任意の実数 1-D を非負の光子レート プロファイルとみなして Poisson 標本化する」op(photon_sample の 1-D 版)。 負値の扱いを明示引数にすれば黙った整流にならず規律を破らない。 既存の非負出力 1-D op(funct1d.abs_funct_1d は実測 min 0.0023、 dsp.envelope は実測 min 0.749 で、どちらも非負が保証される)は、その橋が 在れば signal -> counts の自然な前段になる。詳細は報告を参照。
opspiv.py
- L25 — * ★
flow2d を新設した。既存の flow_dense は述語が ndim == 4 and shape[0] == 3(3-D シーンフロー)で、2-D の (2, h, w) はそもそも該当しない。名前を借りると台帳が 「3 成分を返す」と宣言しながら 2 成分を返すことになり、宣言が嘘になる。 型を増やすときの本 repo の条件(「種を持つ op が無ければ永久に未実行に なる」)は満たしている: 生成が 7 op(cross_correlate / multipass / deform_pass / ensemble_correlate / replace_outliers / to_velocity / sample_at_windows)、消費が 13 op(場の量 8・可視化 2・検定 2・評価 3 の重なりを含む)で、族の中で生成と消費が閉じている。
- L35 — ★ 出口(
visualise の 2 op)を必ず持たせている —— 作れるが見られない 型は、連鎖の途中で行き止まりになり「狭い sort」を生む。 両方向の fail-closed も実測で確認済み: reprconv.flow_magnitude に 2-D フローを渡すと ValueError(「(3, D, H, W) を取る」と名指しで拒否)、 piv_vorticity に 3-D シーンフローを渡すと ValueError。 * 入力の画像対は image2d —— 粒子画像は 2-D の実数場そのもので、 既存の 2-D op(平滑化・閾値・背景差し引き・図注)が意味を保ったまま 使える。輝度が [0,1] に収まる保証は無いが、それは astrostack の 合成結果と同じ立場。 * piv_outlier_mask は mask —— bool の 2-D で述語どおり。 dem_stream_network が nan を持つために mask を名乗れなかったのとは 違い、こちらは欠測を True(外れ値)側に畳んであるので bool で閉じる。 * 統計は table(dict)。piv_error_stats / piv_peak_locking。 * 速度への変換 piv_to_velocity の出力も flow2d —— 単位が px/frame から m/s に変わるが型は同じ。ここは正直に書いておく: 型では単位を守れない。だから両方のスケールを必須引数にしてある (demops の cell_size と同じ判断)。単位を型で分ける案も検討したが、 m/s を作る op が 1 本しか無く、消費する op が 1 本も無い型になる ——「証拠が出てから増やす」の順序に反するので採らなかった。
opsrangedoppler.py
- L108 — ★訂正の記録: 本モジュールの初稿は「real では速度の符号が失われる」と 書いていたが、それは誤りだった(レンジ軸だけの 1-D 実信号では 正しいが、2 軸そろうと符号は保持される)。テストが先に破れて発覚した。 実際に失われるのは「対のどちらが本物か」と、振幅の半分と、 一意測距範囲の半分である。
_as_beat_cube が dtype 段階で拒否し、 直し方(解析信号を明示的に作る)を名指しする。 ————————————————————————– 狭い sort にしないための入口と出口(実測済みの教訓への対処) ————————————————————————– 本 repo は 2 つの罠を実際に踏んでいる: ① 産む op が無い型は永久に到達不能 (score が 434 op 中ただ 1 件の blocked だった件)、② 既存プールに相乗り させると毎回 fail-closed で弾かれ「発見ゼロ」に見える(photon 族 7/17 が 未実行だった件)。beatcube は両方に手当てしてある: 入口(beatcube を産む op) : fmcw_beat_simulate(引数のみ、入力型なし) fmcw_window_apply(beatcube -> beatcube) 出口(既存 sort へ戻る op) : range_doppler_map -> image2d(最大プール) fmcw_range_profile -> signal beamform_delay_sum -> signal beamform_doa -> table 入口が「引数だけの源」である点は tcspc_simulate(入力型なし -> counts)と 同じ形なので、連鎖ファザーには counts と同様に 専用の生成器が要る (親への申し送り事項。生成器の実体は報告に実行確認済みで載せてある)。 出口は image2d と signal という本 repo で最大級のプール 2 つに落ちるので、 jones(2 op)や countrate(2 op)のような閉じた狭い sort にはならない。
opsreprconv.py
- L257 — ★
flow は 1 つの述語では書けない。密 (3,D,H,W) と散在 (N,3) が同じ型名で 同居しているため、両方を通す述語にすると何も守らず、片方に決めると既存の 4 op のうちどれかが必ず TYPEMISS になる。分けるのが正しい(video を voxel から分けたのと同じ判断)が、それは既存 op の宣言を書き換える作業で 本モジュールの担当外なので、ここでは提案だけ置く。
opsvolcolor.py
- L63 — ★ ただし既存
labels 述語は ndim >= 1 で 2-D のラベル画像と 3-D の ラベルボリュームが同居している。本モジュールの 11 op は 2-D を渡されると 全部 ValueError になる(fail-closed)ので、取り違えが黙って通ることは 無い。危険なのは逆で、2-D の種しか無いプールでは 1 度も実行されないまま 「発見ゼロ」に見える —— opsphoton が counts で踏んだ罠と同じ形である。 配線側で 3-D ラベル種を必ず注ぐこと(下の「親が配線するとき」参照)。 * voxel — vol_label_overlay が重ねる元のグレーボリューム、および vol_label_color_flicker が受ける 2 値ボリューム。どちらも (D,H,W) の 既存 voxel 語彙そのもので、新語を作る理由が無い。 * rgbimage — 断面と投影の返り (H,W,3)。既存の rgbimage 消費 op(鏡面分離・ 色変換・保存)がそのまま意味を持って使える。ここが rgbvolume 語彙の出口 なので、新語彙が袋小路にならない。 * matrix — vol_label_palette の返り (n+1, 3)。2-D の実行列そのもの。 * table — 形状統計 / 凡例 / ちらつき測定 / 色付きメッシュの集合。
- L77 — ★ 「色付きメッシュの集合」に新語彙を作らなかったのは実測の結果である。 最初は
colormeshes を足すつもりだったが、既存の table 消費 op を全部 洗って vol_labels_to_meshes の返りを渡したところ(2026-09-02 実測、 ops3d / ops1d / opsmath / opsoptics / opslightfield / opsphoton / opsacoustics / opsinterferometry / opscadmap を横断)、table を食う op は 3 件(abcd_matrix / wavefront_stats / istft)しかなく、3 件とも ValueError で fail-closedだった。つまり「混ぜると黙って間違う」条件を 満たさない。満たさないものに語彙を足すと、消費者ゼロの新語彙 = 袋小路が 1 つ増えるだけである(docs/OP_COMBINATION_MATRIX.md の判断基準)。 なお個々のメッシュを mesh sort として下流へ流したいときは [(m["vertices"], m["faces"]) for m in result] と剥がす —— 色を 捨てる操作なので、adapter で暗黙にはやらない。 ————————————————————————– 新語彙 1 つと、その理由(実測に基づく) ————————————————————————– * rgbvolume — (D, H, W, 3) の色付きボリューム。既存 lightfield の述語は ndim == 4 だけなので、色ボリュームは lightfield を完全に満たす。 実測(2026-09-02、(8, 16, 16, 3) の色ボリュームを lightfield の op へ): - lf_refocus / lf_subaperture / lf_epi / lf_depth_from_focus の 4 op が例外も NaN も出さず (16, 3) の有限な結果を返す (それぞれ「再フォーカス像」「部分開口像」「EPI」「深度」を名乗る)。 z 軸を角度軸 V、y 軸を角度軸 U として読んだ、意味の無い有限値である。 - lf_all_in_focus だけは引数不足で TypeError(型の話ではない)。 逆向き(ライトフィールドを vol_label_slice_rgb へ)は shape[3] != 3 で fail-closed する。安全なのは片側だけなので、実行時チェックには頼れない。 zscan を video から分けたのと同じ判断。 入口 = vol_colorize_labels (labels -> rgbvolume) と vol_label_overlay (voxel + labels -> rgbvolume)、出口 = vol_label_slice_rgb / vol_label_mpr_rgb (-> rgbimage)。産む 2・食う 2 で袋小路にならない。
pcseg.py
- L448 — ★
full_matrices=True(既定)は (N, N) の U を確保して捨てる。 2026-09-06 実測: 20000 点で 3.73 s / 3.2 GB、full_matrices=False なら 0.876 ms(4263 倍)で Vt はビット一致。10 万点なら 80 GB で落ちる。 同型が pcseg.fit_plane / measure / ops / camera / pnp3d にもあった (すべて U を捨てている)。静的な門は tests/test_svd_full_matrices.py。
pivops.py
- L470 — ★ 相関の峰が立たない窓(テクスチャが無い・全面一様)は nan を返す —— 0 を返さないのは「動いていない」と「分からない」を混ぜないため。 だが何割が nan なのかは返り値からしか分からず、
flow.mean() が nan になって初めて気づく形だった(2026-09-06)。ここで数える。 実測: 一様な背景に 16x16 の四角だけの画像では 98 窓中 16 窓しか 有限にならない(0.163)。全面テクスチャなら 1.000。
ppf.py
- L126 — ★ 素の PCA 法線は符号が任意で、回転すると 4 割の点で裏返る。PPF の 特徴は法線どうしの角度なので、裏返れば鍵が変わる。実測(400 点、 z 軸まわり): 素の法線だと鍵の一致率が 0/37/90/143 度で 100 / 73.6 / 69.4 / 67.2 %、向き付き法線なら すべて 100 %。
pointcloud.fpfh が踏んでいたのと同じ穴で、同じ日に一緒に直した。
problems.py
- L147 — ★決定的な大域シャッフル(基点を固定し、train/holdout/locked が同じ置換を索引する)を、seed の役割で鍵付けした 3 つの互いに素な帯に分ける(evolve.run は train=seed·holdout=seed+10000·locked=seed+20000 を引くので、seed//10000 mod 3 が帯を選ぶ)。旧来の
off = seed % pool は、pool が 10000 を割り切るときは常に 3 つの窓を同じフレームへ潰していた —— train↔holdout↔locked の沈黙のリークで、train に過適合した champion が「純粋な holdout で手作りに勝った」ように見えていた。純粋な 3 分割には pool >= 3n が要る。それより小さい pool では綺麗な holdout を作れないので、黙ってリークするより拒否する。
profileops.py
- L269 — ★ 最初は「曲率が大きいほう」で書いて、NACA 2412 で後縁を前縁と判定した。 3 点円の曲率は、上下面がほぼ接する後縁で前縁の丸みより大きく出る —— 「前縁は丸い」という直観が、輪郭上の 3 点で測ると逆転する。
- L276 — ★ 後縁が開いていると、最遠 2 点は後縁の角の片方を拾って弦が傾く。 隙間の中点に取り直してから、前縁を「その中点から最も遠い点」に決める。 これをやらないと対称翼でもキャンバーが後縁の半隙間ぶん出る(実測 0.001257)。
- L642 — ★ 合わせる前に同じ取り方で取り直す。弦の枠(とくに後縁の中点)は点の 置き方にわずかに依存するので、生の輪郭と取り直した輪郭を突き合わせると、 同一の形でも 0.02 度の回転と 7.8e-4 の並進が入る —— それがそのまま 偏差の床(実測 rms 6.05e-4)になっていた。比べるものは同じ土俵に載せる。
- L653 — ★ 点対点ではなく点対折れ線で測る。等弧長に取り直しても両者の位相は 一致しないので、対応を番号で取ると位相のずれがそのまま偏差になる (実測: 同じ形を自分と比べて rms 6.05e-4 —— 検出したい欠陥と同じ桁)。
realdata.py
- L38 — ★公開する図に使ってよいのは
public の列が真のものだけ。 研究・教育目的の引用付き利用に留めるものは cite を持つ。
- L90 — ★skimage は同梱の部分集合しか持っておらず、残りは実行時に pooch で取りに行く。取りに行けないものはこの repo では使わない (PoC が回線に依存すると、落ちた理由が実装かネットワークか 分からなくなる)。
reprconv.py
- L149 — ★ 整数 dtype への変換は キャストの前に 生の値を検査する。 敵対的検査で見つけた穴(2026-09-02):
np.asarray(nan, dtype=int64) は 例外を出さず INT_MIN を返し、キャスト後は dtype.kind == 'i' なので 下の非有限検査を素通りする。3.7 のような非整数も黙って 3 に切り詰まる —— 添字が 1 ずれた結果が、例外もなく返る。まさに変換 op の嘘そのもの。
- L1080 — ★ 実バグの回帰点。最初ここを
np.maximum(sigma, finfo.tiny) にしていた。 重複点で sigma = 2.2e-308 になり、gaussians_to_voxel の sigma ** 3 が アンダーフローで 0 になって 0 除算 -> NaN。 「0 を避けた」つもりが、下流で NaN を生む値に置き換えていた (例外も出ないまま体積の一部が NaN になる = 黙って間違う典型)。 重複点は「間隔が測れない」のだから、番兵で埋めずに fail-closed にする。
rust/fullseye_core/examples/python_ctypes.py
- L42 — ★第 5 引数 fs_dtype_t。2026-09-14 までヘッダにだけ在って実装と FFI 宣言に 無かった引数。ctypes は引数の数を検査しないので、抜けても黙って動く。
sample_data.py
- L147 — ★入れた理由: 展示 111-113 で「合成は自分が知っている壊れ方しか作れない」 (実写 6 本で 9 件の不具合が出た前例)ことが改めて出た。PoC はオフラインで 閉じたまま、実データに差し替える入口だけを台帳に置く。 commercial=”check” 以上は源のページを読んでから使うこと。
scene_registry.py
- L19 — ★配布物にローカル絶対パスを焼き込まない。ここは自分のマシンの作業物を指していた ので、他人が pip install した環境では黙って落ちる(しかも「場面が無い」ではなく 「その場面だけ静かに欠ける」形で)。環境変数で受け、未設定ならその場面を登録しない = 在ると偽らない。
loco_mujoco は入っていれば自分で在り処を知っているので探す。
sdf_ops.py
- L293 — ★足した理由は実測:
poc_dfm_thickness_overhang と poc_cad_scan_deviation が # 「機械部品は円筒穴・面取り・フィレットでできているのに、プリミティブが球と # 直方体しか無いので CSG で組めない」と報告し、両方とも面ごとの解析式を自前で # 書いていた。ここにある 4 つはすべて閉形式で厳密(外側は最近表面までの # ユークリッド距離、内側は最近面までの負値)なので、真値を持つ合成部品を # CSG だけで組めるようになる。 # ————————————————————————— #
specops.py
- L810 — ★これは染色と撮像系の両方に依存する値で、万能の定数ではない —— 自前のスライドで定量するなら、単染色のスライドを撮って :func:
stain_vectors_from_patches で測り直すこと。
- L842 — ★3 本目は「残り」。2 本だけだと 2x3 で逆行列が無く、擬似逆を使うと 残差が黙って 2 本へ配られる。直交な 3 本目を立てて、行き場のない 密度をそこに集める(= あとで残差として読める)。
studio.py
- L273 — ★図そのものを右クリック(ユーザー 2026-09-06:「図で表示したものを 右クリックしてクリップボードにコピーできるといいね」)。この repo の Studio UI 規約 —— 表示系は右クリックからも一通りできること。 下のボタン列と同じことができる(どちらか一方にしない)。
- L6119 — ★図の受け皿。例は
examplefig 経由でここへ PNG を書く。環境変数を 渡さない実行(CLI)では 1 枚も書かれないので、ギャラリーから 走らせたときだけ絵が出る(例の数値と速度は変わらない)。
- L6275 — ★図の受け皿。例は
examplefig 経由でここへ PNG を書く。環境変数を 渡さない実行(CLI)では 1 枚も書かれないので、ギャラリーから 走らせたときだけ絵が出る(例の数値と速度は変わらない)。
tests/conftest.py
- L28 — ★Studio の設定をセッション全体で使い捨て ini へ逃がす。 # ————————————————————————— #
QSettings("Fullseye", "Studio") はネイティブ格納庫(Windows ならレジストリ HKCU\Software\Fullseye\Studio)に書く。隔離を個々のテストファイルに置いて いたので、置き忘れたファイルから利用者の実レジストリが汚れていた。 2026-09-05 の監査で実害を確認: recent_files 10 件のうち 8 件が pytest の 一時パス、system\operator_timeout_ms などの実値も残っていた。 (隔離は 3 ファイル中 2 つにしかなく、test_studio_params.py が素通しだった。) 個別に足すのをやめ、セッション autouse でここに 1 つだけ置く。 環境変数は studio._settings() が見る唯一の入口なので、これで全テストが覆われる。
- L44 — ★optional backend が要るテストの宣言。 # ————————————————————————— # CI の注記には長らく「torch/kornia は入れない(対応テストは graceful skip)」と 書いてあったが、2026-09-05 の実測でそれは事実ではなかった —— 対象テストは skip せず
ImportError: this operator needs the optional 'torch' backend で 落ちていた(14 件)。注記だけがあって、それを機械で確かめる仕組みが無かった。 ここで宣言を 1 つの入口にまとめる。狙いは 両方向: * backend が無い環境 → skip(注記を事実にする) * backend が在るはずの環境 → skip を許さず失敗させる (FULLSEYE_REQUIRE_OPTIONAL=1。CI の py3.11 ジョブがこれを立てる) 片方向だけだと、本物の回帰が静かに skip へ化ける (feedback_failsoft_hides_permanently_dead_ops と同じ形)。
- L192 — ★2026-09-14 追加。ここまで探針バンクは 6 sort しか無く、901 op のうち 151 本 (16.8 %)が契約ゲート 3 本(例外を投げない / 非有限を出さない / 決定的)を 一度も実行されていなかった ——
PROBELESS_OPS_BUDGET = 151 というラチェットで 本数だけ凍結し、「本来の直しは BANKS を全 in_sort へ広げること」と自分で書いて あった。その本来の直しをここで入れる。 形の出どころは推測ではない: backends_bridge._EMPTY_OF が 12 sort すべての 正準の最小値を宣言しており(そこが sort の定義そのもの)、problems.py の _points_stack / _signal_stack などが実データの作り方を持っている。 各バンクは既存の作法に合わせ、普通の値・定数 0・定数 1・退化形を混ぜる (定数と退化形が「走った」と「意味のある出力」を分ける —— [[feedback_ran_is_not_meaningful_output]])。 ————————————————————————— #
- L215 — ★点群は連結なものと非連結なものの両方を置く。
tb_geodesic_distances が 不達を inf で表すのは契約どおりで、ops.NONFINITE_IS_MEANINGFUL に 「1.0 に潰すと『届かない』が『近い』に化ける」と宣言済み。 ここで一度 normal をわざと連結にして有限性ゲートを緑にしかけたが、 それは欠陥を隠す方向だった —— 直すべきは門が台帳を見ていないこと。 normal は橋でつないだ現実的な形、two_clusters は非連結を撃つ探針。
- L263 — ★特異行列は必ず置く。 一度ここから外しかけたが、それは誤りだった ——
tb_mat_cond が特異行列で inf を返すのは契約どおりで、ops.py の NONFINITE_IS_MEANINGFUL に「厳密に特異な行列は s_min=0 なので inf が 正しい答え。有限に潰すと『十分に良条件』と読めてしまう」と既に宣言済み だった。落ちていたのは op ではなく、有限性ゲートがその台帳を見ていない こと。探針を削って緑にするのは、欠陥を隠す行為。 (同じ註に 2026-09-05 の教訓が書いてある ——「自分の probe では特異行列を 作っていなかったので tb_mat_cond を取りこぼした」。探針から外すのは その取りこぼしをわざと再現することになる。)
- L381 — ★新規(2026-09-14): ここまで探針が無く、契約ゲートを一度も通っていなかった 5 sort = 101 op。残る 6 sort(video / qimage / cimage / lightfield / beatcube = 50 op)は形が複素・4-D で退化形の設計に手間が要るため、 一度に全部入れて切り分け不能にしないよう次の段で足す。
tests/test_abi_apply.py
- L78 — ★target dir は 別に切る。最初は
target/release(既定)に建ててそこから直接ロードして いたが、同じプロセスで後に走る test_rust_abi_parity.py が cargo build --release (feature なし)で同じ DLL を書き換えようとし、ロード済みでロックされているので ビルドに失敗 → 36 件が黙って SKIP になった([[feedback_zero_findings_may_mean_never_executed]])。 建てる場所を分け、ロードは tmp へのコピーから行う。
- L49 — ★このパーサは「タグから最初の
; まで」を宣言とみなす。だからタグと 宣言のあいだに ; を含む散文があると、宣言が見つからず collection 中に 死ぬ —— そして pytest はファイル 1 つの collection エラーで スイート全体を中断する(2026-09-14 実測: Interrupted: 1 error during collection で 12,000 件が 1 件も走らず、それでも runner の exit code は 0)。 [[feedback_test_import_kills_collection]] と同じ族なので、何が悪くて どう直すかをここで言う。黙って「malformed」とだけ言うと、壊した本人が ヘッダの書式規則に気づけない。
- L234 — ★2026-09-14:
FsValueError を足した。それまで例外は 2 種しか無く、 種の違う失敗が同じ status に潰れていた —— 逆さの区間は契約では FS_E_INVALID_ARG なのに FsTypeError(= FS_E_TYPE)を投げていた。 差分テストが「どちらも拒否した」までしか見ていなかったので素通りした。
tests/test_abi_signatures_match.py
- L82 — ★
[A] + [B] * 3 のような式で書かれた argtypes がある。最初この形を 数えられず fs_measure_all を「1 引数」と誤読して門が 3 件赤になった —— 門のパーサが弱いのを実装の欠陥と読まない。 行末までを 1 宣言として 取り、[...] の各塊の要素数に * N の倍数を掛けて合計する。
- L180 — ★
cl に .h を直接渡してはいけない —— MSVC は拡張子で言語を決めるので 「ソースファイルの種類は認識できません」と警告だけ出して rc=0 を返す。 検査が 1 行も走っていないのに緑になる、最悪の形 ([[feedback_ran_is_not_meaningful_output]]。2026-09-14 に実際そう読みかけた)。 #include する小さな .c / .cpp を作って /Zs(構文検査のみ)を掛ける。
- L190 — ★引用は 1 段も挟まない。
subprocess にリストで渡すと Python が 引数を再クォートし、内側の " が \" に化けて cmd に届く (実測のエラー: '\"C:\Program Files...\vcvars64.bat\"' は認識されて いません)。バッチファイルに書き出して、それを叩くのが確実。
tests/test_annotate_bold_italic.py
- L59 — ★重ね打ちは横にだけ太る。上下に太る縁取りだと和文のふところが埋まる (2026-09-09 実測: 11pt の「量 値 面積」が黒い塊になった)。
tests/test_astrostack.py
- L1053 — ★2026-09-08: 3 つ目の戻り値 vote_margin(2 番手の山 / 1 番手)が増えた。 星野なら山は 1 つなので小さいはず —— それもここで固定する。
tests/test_backends_typed_liveness.py
- L57 — ★この 1 本については記録が 3 つあった —— ここ、
gen_op_figures.DOMAIN_MISMATCH、 そして op 自身の 0/60 という実測。それでも「登録されているのに一度も走らない」状態は 続いていた。知っていることと、判定に使っていることは別(KNOWN_ISSUES §42)。
tests/test_blob2d.py
- L442 — ★物体が 3 つとも別の形であること。同じ形を並べた種だと circularity も holes も全部同じ値になり、「どのノブでも同じ数を返す op」を見逃す。
tests/test_caltab.py
- L121 — ★ゲートが発火するかは環境依存なので主張しない。値が隠されず返ることだけ見る。
tests/test_ci_wheel_check_paths.py
- L68 — ★returncode は見ない。この検査の対象は引数の解決であって、 wheel の中身ではない。中身の判定は環境に依存する —— 実測 2026-09-05: PYTHONPATH でソースを見せている環境だと、スクリプトが repo 直下を sys.path から外す仕様のせいで一部モジュールが import できず NG になる (pip install した環境では起きない)。ここで returncode を見ていたため、 Linux でこの検査が「パス解決の問題」に見える形で落ちていた。
tests/test_collection_sizes.py
- L64 — ★OPS3D は {op 名: メタデータ dict} の平坦な表。
sum(len(v) for v in values()) と数えると各 op のメタデータのキー数の総和(2,492)になり、意味の無い 数字を台帳に刻むところだった(2026-09-08、書く前に構造を見て気づいた)。
- L85 — ★2026-09-08 追加: 説明を貯める 2 つの台帳。説明ほど静かに減るので ここで数える(docs/CAPABILITIES.md と docs/HARDENING.md の元)。
- L260 — ★ここが厄介なのは、このテストが守っている不具合は Windows では再現しないこと。 2026-09-05 実測: Linux(Ubuntu 24.04 / py3.12 / PyPI wheel)で 3 op が退化入力に 対して SIGSEGV。同じ入力を Windows に流しても 1 件も落ちなかった。 だから「ローカルが緑」は根拠にならず、台帳が正しく効いているかを 両方の環境で確かめられる形にしておく必要がある。 ————————————————————————— #
- L267 — ★
ops.NATIVE_CRASHES_ON_DEGENERATE の対照。本体と 1:1 で一致していなければ ならない。片方だけ変えると落ちる —— 本体から消すのも、本体に足すのも、 ここを同時に書き換える(= 人が意図を確認する)ことを要求する。 なぜ対照が要るか: 門の変異テスト(2026-09-05)で、本体から cv_cc_count を消しても 「台帳の op はみな関門を持つ」を見るテストはそのまま通った。台帳から消えた op は ループの対象からも消えるので、検査経路ごと無くなる。守っている SIGSEGV は Linux 専用で、Windows では偶然まともな値が返るから最後の砦も働かない。 独立した情報源(このセット)との等価だけが、両方向を Windows でも捕まえる。 test_the_two_nonfinite_ledgers_agree と同じ形。
tests/test_demops.py
- L440 — ★ 返りは常に (N, 3)。スカラを渡しても (3,) ではなく (1, 3) になる —— 台帳が points = (N, 3) と宣言しているため(2026-09-06、ファザーの TYPEMISS で食い違いが露見して実装を宣言に合わせた)。
tests/test_docs_index_numbers.py
- L37 — ★op 集合は環境で変わる(Linux CI は torch/kornia/mahotas/xfeatures2d が無く 859 op、手元は 885)。手元で生成した文書と生きたレジストリを比べる検査は 満杯の環境でだけ意味を持つ —— test_opdocs と同じ規約で、揃っていなければ skip(理由に欠けている backend 名が出る)。2026-09-07 の CI で 22 件が これで落ちた。環境に依らない検査(ファイルの実在・中身の量・図の実在)は そのまま走る。
tests/test_docs_index_reachable.py
- L42 — ★op 集合は環境で変わる(Linux CI は torch/kornia/mahotas/xfeatures2d が無く 859 op、手元は 885)。手元で生成した文書と生きたレジストリを比べる検査は 満杯の環境でだけ意味を持つ —— test_opdocs と同じ規約で、揃っていなければ skip(理由に欠けている backend 名が出る)。2026-09-07 の CI で 22 件が これで落ちた。環境に依らない検査(ファイルの実在・中身の量・図の実在)は そのまま走る。
- L80 — ★Markdown 記法だけ見ると足りない。
docs/GALLERY.md は表の中で <img src="..."> を 14 か所使っており、素朴な ]( の走査では 1 つも 見えない(Codex の敵対的レビューで判明、2026-09-06)。生の HTML も見る。
- L189 — ★マーカーの重複を許すと、古い表がもう 1 つ残ったまま緑になる。 生成器は最初の start〜end しか書き換えないので、2 つ目は永久に古いまま 公開され続ける(Codex の敵対的レビュー、2026-09-06)。
- L210 — ★「20 行あって 4 つの次元名が見える」で通していたが、それでは数百 op 落ちても緑になる(Codex の敵対的レビュー、2026-09-06)。次元ごとの 実数と 1 つ残らず突き合わせる。
- L249 — ★どこが違うかを出す。出さないと、全体スイートでだけ落ちる ような順序依存(レジストリ汚染など)を追えない。
- L312 — ★件数と名前だけでは、型の契約(in_sort/out_sort)・カテゴリ・HALCON 対応・ tier が丸ごと古いまま緑になる(Codex の敵対的レビュー、2026-09-06)。 RAG は型が繋がる op を選ぶのに in_sort/out_sort を読むので、そこが古いと 繋がらない鎖を自信満々に提案する。中身ごと突き合わせる。
- L457 — ★生成物が「中身か」を見る —— 一致だけ見る門は、両方が空でも緑になる # ————————————————————————— # 2026-09-06 の実測。下回ったら落ちる(上げるのは自由)。
tests/test_dsp.py
- L338 — ★最大は高調波: period / (1/f_max_bin) が整数の近くに来る
tests/test_example_scripts_run.py
- L48 — ★2026-09-09、この門を入れた最初の CI で 7 本が py3.12 で落ちた(py3.11 は緑)。 CI は意図的に py3.11 だけ torch / kornia / mahotas / opencv-contrib を入れ、 他の版では入れない。テスト側には
requires_backend という宣言の仕組みが既に あったのに、例を走らせる門にはそれが無かった —— 仕組みがあることと、 全経路が通っていることは別。 gallery2d_* は「その族の op を全部動かす」ギャラリーなので、契約そのものが どの backend が入っているかに依存する(op 名を直書きしてレジストリと突き合わせ、 1 つでも欠けると「OPS に余分」で落ちる)。だから族ごと宣言する。残り 2 本は torch を直に使う(fit_zernike / match_logpolar_z)。 完全環境(CI の py3.11、FULLSEYE_REQUIRE_OPTIONAL=1)では skip が失敗に なるので、宣言の付け過ぎも付け忘れも両方向で落ちる。
- L87 — ★PYTHONPATH を渡さない(この門の要点)。利用者は環境変数を設定しない。
tests/test_flyvision.py
- L328 — ★ The MTF identity is a small-footprint approximation and is NOT claimed
- L329 — ★ far from the optical axis: at ~35 deg elevation the measured transfer
- L330 — ★ already departs from exp(-…) by more than the on-axis tolerance. This
- L331 — ★ assert pins that hole so a future “curvature-corrected” resample has a
- L332 — ★ failing test to turn green rather than a silent regression to argue about.
tests/test_fslib.py
- L330 — backend 横断の一致 —— ★2026-09-14 に実際に壊れていたところ ————————————————————————— #
tests/test_fullseye_3dgs.py
- L78 — ★道具の有無と資産の有無は別。ここは mujoco の有無だけを見ていたので、 Menagerie が無い環境では
scene_registry.resolve() が返す None を掴んで TypeError になった。同ファイルの test_scene_resolution_via_registry は 既に資産の skip を持っており、作法が兄弟に適用されていなかった。
tests/test_gaits.py
- L99 — ★2026-09-14: ここは
resolve() の戻りを検査せず spec["xml"] を引いていた。 scene_registry が実在しない場面に None を返す設計(資産が無い環境では 正しい振る舞い)なので、資産チェックアウトが無いと TypeError で落ちる。 同じファイル群の test_fullseye_3dgs.py は既にこの skip 作法を持っていた —— 作法が兄弟に適用されていなかった ([[feedback_same_bug_class_recurs_check_siblings]])。
tests/test_glassmirror.py
- L91 — ★直感と逆だった: 「銅は金より赤い」と思って cu[2] < au[2] を書いたら落ちた。 公開値でも Au の R(450 nm) ≈ 0.40 に対し Cu ≈ 0.56 で、青は銅の方が多い (= 金の方が飽和した黄色)。表ではなくこちらの思い込みが誤りだった。
- L175 — ★ 波長を第 1 引数にした理由(台帳の「先頭がデータ」規約)。配列を頂角へ 渡すと以前は素の TypeError が出ていた。
tests/test_honest_summary_arithmetic.py
- L41 — 「無ければ理由を言って skip」にする —— ★2026-09-08 の CI がここで赤に なった: 手元にあるものを CI にも在ると思い込むと、手元だけ緑になる (
feedback_gate_computed_a_verdict_then_discarded_it と同じ型)。
tests/test_mcp_images.py
- L312 — ★最初
ones + inf にしていて、有限部が定数なので免除 op でも「定数」判定になり 落ちた —— それは診断器が正しい。確かめたいのは「免除 op なら非有限を異常と 言わない」だけなので、有限部に変化のある入力にする。
tests/test_mcp_server.py
- L57 — ★引数名を
name にしていて _call(4, "fullseye_op_help", name="gaussian") が TypeError になり、subprocess の実 stdio 往復が 1 度も走らないまま 23 件が緑だった(2026-09-15)。走らなかった検査は無いのと同じ。
- L105 — ★最初
gaussian が先頭と決めつけて落ちた。gauss_filter と gaussian は同じ HALCON 別名を共有する別 op で、api.find_op は name == halcon の正典を優先する。 検索もその規約に揃えたので、正典が先頭・gaussian が上位に居ることを見る。
- L249 — ★以前の被験者は台帳経由で索引に入ったこと(= 索引が台帳を数えている)も見る
- L316 — ★同日実測: 4 層で 480 枚が「どこにも無いノート」に見えたが、5 層目(ledger)で 480 / 480 が解決した。ここが 0 でなくなったら、まず引き忘れた層を疑うこと ([[feedback_search_all_tiers_before_declaring_a_gap]])。ノートの残骸と決めつけない。
tests/test_no_local_paths_in_shipped_code.py
- L22 — ★
tomllib は Python 3.11 から。モジュール先頭で素の import をすると 3.10 で収集が中断し、テストが 1 件も走らない —— 2026-09-05 に hypothesis で 同じことを踏んだ直後に、この検査で再発させた(CI py3.10 が collection error)。 import 失敗は必ず skip に落とす。
- L53 — ★2026-09-14 追加: MSVC の標準インストール先。
fullseye_3dgs._find_cl_dir() が cl.exe を探すための候補として持っている。これは「私のマシンの作業物を 指している」のではなく「Visual Studio インストーラが決める場所」なので、 環境変数に追い出しても他人の環境で当たりやすくはならない(むしろ探索が 効かなくなる)。glob で実在を確かめてから使い、無ければ None を返す作りに なっていることを確認済み。 ※ _WIN_ABS は空白入りの語を 2 つ目までしか拾わないので、切り出される断片は C:\Program Files\Microsoft までになる。許可文字列は実際に切り出される形に 合わせる —— 正規表現の結果を見ずに「あるべき文字列」を書いて外した(2026-09-14)。
tests/test_op_contract_property.py
- L32 — ★hypothesis が無い環境ではこの 1 ファイルの import 失敗が全体を止める —— pytest は collection error で残りを走らせずに中断する(2026-09-05、CI が 2 分で 死んでテストが 1 件も走らなかった)。skip に落として他を巻き込まない。
tests/test_op_contracts.py
- L52 — ★2026-09-14 実測: 901 op 中 151 本(16.8 %) がこの状態で、空ループを 1 周 しただけで緑を返していた —— 「門が判定を計算した直後に捨てる」の親戚で、 こちらは 判定を一度も計算しない。まず skip で見えるようにし、
test_probeless_ops_do_not_grow で本数を台帳に固定する(減る分には通る)。
- L56 — ★2026-09-14: 本来の直しを入れて 151 → 0 にした。 上に「本来の直しは
conftest.BANKS を全 in_sort へ広げること」と自分で書いておきながら、 ラチェットで本数を凍結したまま 9 日が過ぎていた —— 台帳は免罪符になりやすい ([[feedback_never_weaken_the_probe_to_get_green]])。 足したのは 11 sort: points(56) / signal(27) / video(16) / qimage(11) / cimage(9) / counts(8) / lightfield(8) / rgbimage(6) / matrix(4) / beatcube(4) / keypoints(2) = 151 op。形は推測ではなく backends_bridge._EMPTY_OF (12 sort すべての正準の最小値)と problems.py の入力生成器から取った。 これで 901 op すべてが 3 つの契約ゲートを実際に通る。 0 になった以上、このラチェットの役目は「増えたら落とす」に変わった。 新しい in_sort を足した人は conftest.BANKS に探針も足すこと —— 足さないと その op たちは「登録されているのに一度も実行されない」状態に戻る。
- L98 — ★非有限がその op の意味を運んでいるものは、この門の対象外。判断は ここで持たず
ops.NONFINITE_IS_MEANINGFUL を単一の正本として引く (test_backends_typed_liveness.KNOWN_NONFINITE_BY_CONTRACT が同じ表の 写しで、一致は別の検査が見ている。3 つ目の写しを作らない)。 2026-09-14: 探針バンクを 6 sort 広げたとき、ここで tb_mat_cond(特異行列の 条件数 = inf)と tb_geodesic_distances(不達 = inf)が落ちた。一度 探針から特異行列と非連結点群を外して緑にしかけたが、それは誤り —— 台帳は「inf が正しい答え」と既に宣言しており、落ちていたのは門がその 台帳を見ていないことだった。探針を削って緑にするのは欠陥を隠す行為で、 しかも同じ台帳の註に「自分の probe では特異行列を作っていなかったので tb_mat_cond を取りこぼした」という 2026-09-05 の教訓が書いてある。
tests/test_op_discovery.py
-
| L229 — ★素通しですらない: フォールバックは画像の契約 [0,1] へ切り詰めて返す。 負の半分が 0 になった信号は「フィルタした信号」に見えるので、 これは黙って嘘をつく。max |
差 |
= 1.0、最小値 -1.0 -> 0.0。 |
tests/test_op_example_coverage.py
- L58 — ★母集団を「配布物の側」から数える ratchet(2026-09-06) # ————————————————————————— # 2026-09-06 の実測。この数より悪くしないための歯止めで、目標値ではない。 台帳 op 1,002 本のうち例索引に入っているのは 349 本しかなく、上の 2 本の 「100 %」は母集団が 3 層のうち 2 層しか無いために成り立っていた。 経緯と族別の内訳 = docs/KNOWN_ISSUES.md §38。
- L32 — ★op 集合は環境で変わる(Linux CI は torch/kornia/mahotas/xfeatures2d が無く 859 op、手元は 885)。手元で生成した文書と生きたレジストリを比べる検査は 満杯の環境でだけ意味を持つ —— test_opdocs と同じ規約で、揃っていなければ skip(理由に欠けている backend 名が出る)。2026-09-07 の CI で 22 件が これで落ちた。環境に依らない検査(ファイルの実在・中身の量・図の実在)は そのまま走る。
- L203 — ★2026-09-08: 第三者バックエンドの版に依存する op は台帳から外して数える。 この台帳は「図を作った環境」で書かれ、「テストを走らせる環境」で検証される。 cv2 の実装は版で変わるので、手元(opencv 5.0)で効かないつまみが CI (opencv-contrib 4.x)では効く —— 実測で
xcv_grabcut の b がそれだった。 台帳が主張してよいのはどの環境でも成り立つことだけ。版に依存する分は 主張しない(嘘の台帳を持つより、狭くて正しい台帳のほうがよい)。
tests/test_op_probe_ledger.py
- L76 — ★2026-09-08 に足した。それまでこの門は image / region / color / volume の 4 つに しか入力を作っておらず、
contour 65 / points 57 / signal 26 / video 16 … 217 op(レジストリ 901 本の 24 %)を “uncallable” として素通りさせていた。 「門が正しい場所に立っている」ことと「門が全部を通す」ことは別 —— 広げた初回に tb_angle_3points が探針では一度も走れないこと(登録は points→feature なのに 実体は 3 本のベクトルを取る)が出た。
- L192 — ★2026-09-08 の CI(py3.10 / py3.12、torch なし)がここで赤になった —— 探針を全 sort に広げた初回に、torch を要る op(
tb_points_to_voxel)へ 初めて到達したため。「壊れている」と「この環境に無い」は別の判定で、 混ぜると環境差が実装のバグに化ける。満杯の環境 (FULLSEYE_REQUIRE_OPTIONAL=1)では従来どおり失敗にする。
tests/test_opdocs.py
- L212 — ★2026-09-03: 全 backend の _safe が backend_safe.guard に集約されたので、 qualname の文字列一致ではなく guard が立てる構造化マーカーで判定する (guard は qualname にも “_safe(…)” を残すが、そちらは表示用)。
- L1178 — ★見つからなかった理由:
ops.REGISTRY(899)と 2-D ノート(899)は一致するので、 レジストリ側から数える限り「欠落ゼロ」に見える。一度そう結論して間違えた。 だからこの門は tier をまたぐ索引の側から数える (memory: feedback_search_all_tiers_before_declaring_a_gap)。 ————————————————————————— #
tests/test_packaging_foundation.py
- L170 — ★2026-09-07: 手元の wheel に sample_sources_ai が 42 MB 乗っていた(96 MB)。 原因は古い build/lib/ のキャッシュ(package-data から外す前の残骸が詰め直される)。 設定を読む検査では捕まらない事故なので、wheel 実物の側を tools/ci_wheel_check.py (unshipped_present)と ci.yml のサイズ上限が見る。ディレクトリも package の外へ 移した(tools/fops_article/)。ここでは除外の明示を要求する(保険)。
tests/test_pivops.py
- L621 — ★名前レベルの
PARAM_HINTS だけを見ると門がファザーより狭くなる。 chain_fuzz._bind_args は op 名で狙い撃つ OP_PARAM_HINTS も見るので、 ここでも両方を見る(2026-09-06: dic の window / method を OP_PARAM_HINTS に置いたら、実際には束縛できているのにここだけ落ちた)。
tests/test_poc_scripts_run.py
- L57 — ★2026-09-08: 固定 6 をやめて CPU 数に合わせる。共有ランナー(2〜4 vCPU)では 6 並列が 1 本ずつを遅くするだけで総時間が縮まらず、PoC が 84 本に増えたところで ジョブごと pytest の 900 秒 timeout に落ちた(py3.10 / 3.12)。手元(12 コア)は これまでどおり 6 以上で回る。
- L73 — ★
PYTHONPATH は渡さない(2026-09-09)。長らく PYTHONPATH=<repo> を 渡していたが、それは利用者がしない設定で、門が事故の起きる場所から 1 歩ずれる ことを意味していた —— 同じ盲点で examples/piv_flow_from_particles.py などが 「チェックアウトからそのまま走らせると ModuleNotFoundError」のまま残っていた (あちらは走らせる門すら無かったので気づかれなかった。test_example_scripts_run.py)。 PoC 側は 116 本中 108 本が自分で repo 直下を sys.path に足しており、残り 8 本は fullseye しか import しないので、外しても全数が通る(実測済み)。
- L91 — ★失敗時は stdout の末尾も返す。PoC は所見と「どの検査が落ちたか」を stdout に印字して SystemExit(1) するので、stderr だけだと空のまま 「exit 1」しか分からない(2026-09-07 の CI、py3.10 の poc_ct_fidelity)。
- L100 — ★2026-09-07: ここは長らく 0 を返していた ので、下の
assert code == 0 を素通りしていた —— 合否を計算した直後に 捨てる門(実測: PASS を一度も印字しない PoC が 3 本 —— poc_dic_strain / poc_photoelasticity / poc_thermography_ndt)。 -2 を返して落ちるようにする。
- L122 — ★この門は 84 本の PoC をまとめて 1 回走らせる(session fixture)。その時間は 最初のテストに計上されるので、pyproject の既定 timeout(900 秒)では共有ランナーで 落ちる。ここだけ広げる —— 既定を緩めると他のテストのハング検出まで鈍る。
tests/test_public_reachability.py
- L71 — ★2026-09-14: この 13 本は 2026-09-05 から wheel に入っていなかったもので、 py-modules へ足した結果ここに現れた。演算子としては
unified._3DGS_OPS が _lazy_call(モジュール名, 関数名) で文字列から登録しているので、利用者には fullseye.op.<名前> 経由で届く。ここに残る 1〜6 本は各モジュールのデモ入口 (render_*_gif など)で、op ではなく絵を作る側。だから内部専用に置く。 —— 「配布から消えていた」を直すと「公開経路から見えない」が現れる、という 二段構えだった([[feedback_registered_only_gates_miss_unregistered]])。
- L88 — ★2026-09-15: 33 行すべてが公開経路(fullseye.<名前> / .ledger / .op)に届くように なっており、2 番目の検査が「この表から行を消すこと」と 33 件を挙げた。 消した 33: transforms / mosaic / fit_transform / tools_geom / matrix / shapematch / objmodel3d / matching3d / matching / calib / caltab / calibration3d / contours_xld / contours_xld2 / image_channels / filters_freq / filters_flow / regions_setops / regions_gen / region_morph / morph_minkowski / segmentation / image_gen / image_paint / misc_vision / imgops_nary / scattered / inspection / pipeline3d / watershed3d / mesh_decimate / sample_data / scale。 表は空でも残す —— 「出すべきなのに出ていない」ものが次に現れたときの器。名前>
tests/test_raster.py
- L26 — ★素の import だと不在環境で収集ごと中断する(2026-09-05 実測)。
tests/test_rust_abi_parity.py
- L402 — ★契約では FS_E_INVALID_ARG(引数が定義域の外)であって FS_E_TYPE ではない。
FsValueError を足すまでは両方 FsTypeError で、Rust が 1 を返すのに Python は 2 相当を投げる、という状態コードの食い違いが残っていた。
tests/test_shapestats.py
- L196 — ★ 面を自由にすると、片側の一様な広がりは丸ごと吸われる(実測 4.9e-35)。 中点が半分だけ動き、面もそこへ動くので、左右差として残らない。これは この定義の限界であって不具合ではない —— 見たいなら面を外から与えるか、 正中線上のランドマーク(midline)を足すこと。
tests/test_studio.py
- L920 — ★
setDefaultFormat は引数なしコンストラクタにしか効かず、Studio の QSettings("Fullseye", "Studio") はレジストリ固定だった —— この fixture は 何も隔離していなかった(2026-09-05、レジストリに pytest のパスが残っていた)。 本体側の入口 studio._settings() を環境変数で ini に向ける。
- L2029 — ★
QSettings("Fullseye", "Studio") を直に組むと隔離を迂回して利用者の レジストリに書く(2026-09-05 の監査で実害を確認)。設定入口は 1 つに保つ。
tests/test_studio_logic.py
- L22 — ★旧 setDefaultFormat 方式は Studio の QSettings(org, app) に効かなかった。 本体の入口 studio._settings() を ini に向ける(session 全体)。
tests/test_studio_ops_browser.py
- L11 — ★素の import だと matplotlib 不在の環境で収集ごと中断する (pytest は 1 本の import 失敗で残り全部を走らせない)。2026-09-05 実測。
tests/test_videostream.py
-
| L319 — ★Collins (VSAM 2000): 両方とも現フレーム基準。2026-09-05 までこのテストは 連続ペア |
f[t-1]-f[t-2] |
を期待していて、実装の誤りを仕様として固定していた (等速で動く一様な物体で常に全ゼロ —— 下の回帰テスト)。 |
- L43 — ★カタログ・ヒント・アダプタは出荷モジュール
typed_catalog が正本(2026-09-05)。 以前はここに住んでいて、backends_typed が tools/ を sys.path に足して読んでいた —— その結果 wheel では tb_* 143 op が黙って消えていた。向きを逆にした。
- L256 — 事象の位置(点過程)—— point_spectrum の入口。★一様乱数だけにしない: 周期成分が無いと「周期を見つける op」の意味のある挙動を一度も踏まないので、 周期 17.0 の列に 12 個の無関係な事象を混ぜた構造データを種にする (乱数だけの試験は構造の欠陥を隠す、というこの repo の規律)。
- L864 — ★ 非有限が混じった点群は KD 木の構築そのものが生の ValueError で落ちる (scipy: “data must be finite”)。プールは NONFINITE を記録したうえで値を 残す設計なので、汚れた点群がここへ来るのは想定内 —— 建てる側が防ぐ。 2026-09-06 に実際に踏んだ: 新しい族が増えて連鎖の歩き方が変わり、 seed 3_000_0xx でこの経路に当たってファザー自身が停止した(op の欠陥では なく道具の欠陥。束縛できない入力は例外ではなくスキップが約束)。
- L1557 — ★ 2026-09-02 まで
lambda v: True だった = 述語が「有る」と数えられている ぶん、無いより悪い(点検スクリプトも「述語あり」に数えてしまう)。実測で None / 42 / 文字列 / dict まで通していた。 正典は消費側 6 op(reprconv の pairs_to_signal / pairs_to_image2d / pairs_to_table / angles_to_normals / shape_index_to_curvature / polar_to_cscalar)を全部実行して決めた: 6 op とも上の 2 形だけを受け、 それ以外は “pairs: must be (N, 2) or a 2-tuple of equal-length 1-D arrays” で名指しの fail-closed になる(実測)。(2,N) は受けないので、 2-tuple を np.stack で (2,N) に潰していた adapter 3 件は axis=1 へ直した。 長さの違う 2 本(histogram の counts/edges)も「対」ではないので弾く。
- L1667 — ★ 「2 要素ちょうど」は pose(
len >= 2 で info を許す)とわざと違う。 実測 2026-09-02: mesh を 1 引数で受ける既存 consumer 4 件 (face_normals / vertex_normals / mesh_area / vertex_curvature)は 3-tuple に対して “mesh must be a 2-element tuple (vertices, faces)” を 送出し、cadmap の _mesh と render3d._mesh_arrays も 2 要素しか受けない。 つまり この repo の mesh sort の正典は 2-tuple で、余分な要素は 「情報が多い」のではなく下流が全滅する型の嘘になる。唯一の例外だった voxel_to_mesh((v, f, n) を返す)は ops3d.RESULT_ADAPTERS で正典の 並びを取り出すようにした(gicp / vol_label と同じ扱い)。
- L25 — ★このスクリプト自身の置き場所を sys.path から外す。 Python はスクリプトの ディレクトリを sys.path[0] に載せるので、checkout の
tools/ から起動すると wheel 側の venv でも tools/ 配下(非同梱の chain_fuzz 等)が import できてしまい、 「wheel に無いものが見える」状態で数えることになる。2026-09-05 のレビューで、 この門が tb_* 143 op の欠落を見逃していたのはまさにこれ。 併せて cwd も空の一時ディレクトリへ移す(cwd が checkout だと同じことが起きる)。
- L34 — ★cwd を移す前に元の cwd を覚え、以後すべての引数パスをここへ解決する。 2026-09-05 実測: preflight は絶対パスで渡すので手元では通り、ci.yml は相対パスで 渡すので dump が一時 dir に書き捨てられ、compare が FileNotFoundError で落ちた —— 門が本番の呼び出し経路では一度も比較を実行していなかった。 「門は事故の起きる場所に立てる」の 3 度目。呼ぶ側を直すのではなく、 相対パスで呼ばれても正しく動くようにして、この型ごと閉じる。
- L139 — ★2026-09-08: editable 側も見る。それまで
a["failed_backends"] は 集めるだけで誰も読んでいなかった —— 同じ回に examplefig の図の失敗と 同じ型の穴として摘発した。editable の venv は optional 依存が多いので、 版の食い違いで backend が import に失敗しうる。そのとき wheel 側は 「依存が無いから最初から居ない」だけで失敗を記録せず、この比較は緑のまま 通ってしまう。落ちた backend の op はレジストリから黙って消える。
- L92 — ★ここは 2 度間違えられる。ファザーの
run_chain は (1) 入力型 any を「常に揃っている」として扱い(プールから任意に引く)、 (2) OP_ARG_BUILDERS に登録された op は引数を自前で組み立てる。 この 2 つを数えないと、実際には毎回走っている op を「構造的に到達不能」と 報告してしまう(実際に fuse_to_voxel / register_cross で誤報した)。 到達可能性は「型だけ」では決まらない ―― 到達経路の一部はコードの側にある。
- L89 — ★2026-09-14 追加。45,000 ケースを 3 秒で「食い違いなし」と言われたとき、 信じるのではなく自分が printf で挙げた「踏んでいない座標」を足す。 一致したときこそ探針を疑う([[feedback_one_probe_input_is_not_coverage]])。
- L185 — ★2026-09-14: ここは長らく値域だけを振って画素は 0..1 のままだった。相対しきい値は 値域を通して解決されるので、値域 (100,300) では絶対値 100〜300 と比べられ、 100% が空になっていた(実測: (100,300) は 780/780 が 0 画素、全体でも 63% が 物体 0 個)。4000 ケースが 0.6 秒で「食い違いなし」だったのは頑健だからではなく、 connection も measure_all もほとんど踏んでいなかったから ([[feedback_zero_findings_may_mean_never_executed]])。値域を名乗らせるなら 画素もその値域で描く。
- L198 — ★しきい値は画像に実在する値から引く。独立に引いていたときは 41% が 「選択 0 画素」で、物体が 2 個以上あるのは 14% だけだった ——
connection の 分岐(斜め接触・入れ子・多数)をほとんど踏んでいない。乱数で撒くと空ばかりに なるのは、しきい値も探針の一部だから ([[feedback_one_probe_input_is_not_coverage]]: 探針は入力画像だけではない)。 2 割は「当てずっぽう」のまま残す —— 空・全面・範囲外という端も要る。
- L236 — ★R-3 の相対→絶対の写像と画像の形。契約の関数なのに観測していなかった。
- L265 — ★
fs_region_runs は契約が「領域表現の唯一の窓」と呼ぶもの。それを 観測していなかった —— 面積と本数が合っていても、run の切り方が違えば run-length と dense mask は別物として振る舞う(隣接 run を結合するか、 行内の並びは昇順か)。観測していない性質はケース数では出ない。
- L295 — ★並びそのものを観測する。
sorted して比べていたので、物体の順序を逆にする 変異が 3,000 ケースで 1 件も殺せなかった(2026-09-14 の変異解析)。契約は 「最初の run の (row, col) 昇順」と明記しているのに、門がどこにも無かった —— 観測していないものは、どれだけケースを撒いても出てこない。
- L337 — ★R-3 の相対→絶対の写像そのものを観測する(契約
fs_image_absolute)。
- L351 — ★種別を捨てない。ここは長らく固定値 1 だったので、
_status_of を 書いて compare にコード比較まで足したのに、Python 側が常に 1 を 名乗るせいで状態コードの食い違いが構造的に出なかった(変異 m8 が 3,000 ケースで殺せなかった正体)。観測を足したつもりで足しきれて いない、という [[feedback_gate_computed_a_verdict_then_discarded_it]] の型。
- L381 — ★コードの値まで見る。「どちらも拒否した」で止めていたので、 契約が FS_E_INVALID_ARG(1)と決めている所で Python が FS_E_TYPE(2) 相当を投げていても素通りしていた(2026-09-14 に実際そうだった)。
- L390 — ★許容差は値域に対する相対で取る。絶対値で 1e-5 と決めていたら、 値域 (100,300) の画像で 1.04e-05 の差が「食い違い」として報告された —— が、切り分けると Rust vs scipy は float64 のままなら 8.53e-14、 float32 を経由した途端 1.04e-05。つまり
fslib の astype(np.float32) の丸めで、欠陥ではなく私の測り方の欠陥だった(値域比で見ると どの値域でも一様に 1.4〜5.2e-08 = float32 の相対精度)。 [[feedback_second_instance_artifact_not_physics]] と同じ型 —— 驚く結果は物理(実装の違い)で説明する前に道具を疑う。
tools/gen_blas_article_figs.py
- L93 — ★1 スレッドが最速だった範囲を半透明で敷く。線を隠さないよう先に置き、 alpha を低く保つ(帯そのものが主張しすぎると、線の比較が読みにくくなる)。
- L37 — 区分の英語名。★英語版でも見出しだけ日本語のままだった(実測 7 行)—— 中身は
title_en / _summary_en で訳してあるのに、見出しを訳し忘れていて 「切り替えたのに日本語が混ざる」の典型になっていた。ここに無い区分は 原文のまま出す(勝手に訳を作らない)。
- L45 — ★対訳表は op ドキュメントとは別ファイルにする。
opdocs.T を使うと 引いた原文が opdocs.SEEN_STRINGS に載り、既存の「枠の対訳に穴がある」門が 604 件すべてを穴として数えて CI が落ちる —— あの門は「枠の文言は必ず 5 言語 そろえる」ための門で、こちらは「訳せた順に増やす」性質のものだから、 同じ表に混ぜると片方の規律がもう片方を壊す。
- L79 — 1 塊 = ★ を含む行から始まり、同じ字下げで続く
# コメント行の連なり。 Sphinx 風の #: コメントも拾う。# と空白だけを剥ぐと先頭に : が
- L81 — 残り、生成物に「: ★…」と出る(実際に出た)。
: もここで剥ぐ。
- L105 — 次の ★ が来たら別の塊として切る(1 塊 1 主張に保つ)。
- L197 — ★印は訳さず
_(ja)_ に固定する。言語ごとに訳すと機械が数えられない —— tools/i18n_status.py が「印の無い日本語」を数える道具なので、 印が言語ごとに変わると 593 行が「隠れた日本語」に化ける(実際に化けた)。 ja は言語コードで、読み手にも「これは日本語」と伝わる。
- L280 — ★ノートの集合は台帳から取る(ファイルを数え上げない)。 2026-09-06 の敵対的レビュー(Codex)で、ファイルを glob して stem を 数える版が
docs/ops/SAMPLES.md(op ノートではない)を 1 本混ぜており、 索引は 1,842、RAG ガイドは 1,843 と食い違う数を同時に公開していた。 ノートは records から 1:1 で生成されるので、records の名前が「ノートの ある名前」の定義そのもの。ファイルとの一致は tests/test_docs_index_reachable.py が別に見る(消えた/余った を検出)。
- L290 — ★
dir(fullseye) ではなく __all__。dir はモジュール属性(os / sys / warnings / annotations)を含み、しかも他のテストが import した後は 1 つ増える(1094 → 1095)ので、全体スイートでだけドリフト門が落ちた (2026-09-06)。公開面はファサードが __all__ で宣言している 1,091 名。
- L339 — ★索引は人だけでなく AI の検索面でもある(2026-09-06 のユーザーの指摘 「索引って RAG としても使われる部分だよね?」)。op ノートは AI コーディング 支援の検索コーパスを兼ねるので、機械が読む入口を索引に明示する。 半分しか無いものを「全 op」と書くと、RAG は残り半分について自信満々に 間違える —— だから
_honest() の実測行はこの節から外さない。
- L490 — ★2026-09-14: 長らく かな だけを見ていたので、「Studio 北極星」「実測記録」 のように 漢字だけで書かれた題に印が付かなかった —— 非日本語版の読者は それを英語の題だと思ってクリックする(印を付けないのは「読めない」という 事実を隠すことで、無訳より悪い、というのがこの関数の趣旨そのもの)。 題は常に日本語版ファイルから取る(
_doc_title(rel))ので、漢字を足しても 中国語の題を誤って日本語と呼ぶことは起きない。
- L655 — ★Qiita 投稿用の frontmatter(— で挟んだ YAML)は題ではない。中の
title: 行は 下の走査では見出しにも読み飛ばし対象にも当たらず、そのまま索引の見出しになって しまう(「title: ‘…’」と並ぶ)。挟まれた範囲ごと読み飛ばす。
- L94 — ★status=fixed なのに門が無いのは通さない —— 直したという記録だけが 残って再発を止められない状態を、この台帳自身が作らないため。
- L194 — ★リンク先(
docs/hardening/*.md)は日本語で書かれている。英題に 差し替えるのは嘘になるので、題はそのまま出して (ja) を添える —— 非日本語版の読者に要るのは「訳された題」ではなく「これは読めない」 という事実。印は tools/i18n_status.py が数える形に固定する。
- L41 — ★ここは「ただの定数」ではない: 線積分 p = Σ μ·Δx が 10 を超えると exp(-p) が 光子数 1 を割り、対数が飽和して p が頭打ちになる(photon starvation)。 最初の版は μ を 0.55–1.0「/画素」で置いてしまい、p が 30 に達して復元 μ が 50–84% 低く出た。零点(単純逆投影)の方が Dice で勝ってしまい、そこで気づいた。
- L166 — ★材質ごとの数字は 再現率(recall)。「その材質のラベル内で拾えた割合」であって Dice ではない(ラベルの外に出た偽陽性を数えないので、Dice と名乗ると必ず 1.0 に 近づく)。全体の取りこぼし/拾いすぎは下の precision / recall で別に出す。
- L65 — ★ 巻き順は外向き。逆にすると法線が内を向き、render_beauty が 例外を出さずに真っ黒を返す(最初の版がそれで、薄膜の球だけ黒かった)。
- L153 — ★これは下界。
tests/ に op 名が literal で現れるかしか見ていないので、 台帳を舐めて全 op を回す掃引型の試験(for name in ledger: ...)は数えない。 「試験が無い」ではなく「名指しの試験が無い」と読むこと。
- L105 — ★2026-09-08: この表に居た
tb_angle_3points と tb_indices_to_labels は、 「図の定義域の外」ではなく 橋に載せてはいけない op だった。前者は 3 本の ベクトルを取るので点群 1 本では呼べず、後者は 1-D を返すのに宣言 out が labels(→ volume = ndim 3)。どちらも登録されたまま一度も走ったことが無く、 fail-soft がもっともらしい値を返していた。backends_typed._OP_BRIDGE_SKIP へ 移し、この表からは外した —— 図が出ないことの記録は在ったのに、走れないこと 自体の記録がどこにも無かった(門が 2 つあって、片方だけが気づいていた)。
- L115 — ★2026-09-13: op が evolute 検証を得て厳格化。ECEF は地球表面(中心から ~6.4M m)の 座標を要るが、画像由来の合成点は原点付近で必ず楕円体の evolute 内に落ちるため 正しく拒否される(実データでは動く。合成入力では図を作れない恒久的な定義域ミスマッチ)。
- L127 — ★2026-09-07(ユーザー指示「1 枚に纏める必要はない。段階的なもの・条件が複数 あるものは分けて出す」「物によっては疑似カラーのほうが分かりやすい」「複雑なものは アニメーション GIF でも」)。主図
<op>.png に加えて、 <op>.a.jpg / <op>.b.jpg — つまみを 0.1 / 0.5 / 0.9 に振った 3 枚(出力が 変わるときだけ。変わらなければ manifest に理由) <op>.chain.jpg — 前置き op がある op の段階図(画像 → 中間 → 出力) <op>.gif — 出力が動画 / ライトフィールド / 体積のとき、フレーム / 視点 / スライスを順に見せる(静止画 <op>.png が完成形で GIF は追加。Studio の QTextBrowser は 1 コマ目を出す) 疑似カラーは量の場(距離・位相・向き・深度・曲率 …)の出力にだけ掛け、 キャプションに (viridis) と書く。フィルタ系はグレーのまま(色が変わる op に 見せない)。
- L730 — ★「走った」と「意味のある出力が出た」は別(2026-09-07、ユーザー 指摘「out が真っ黒なのはなんだ?」)。空配列を「図あり」に数えると 黒い板が図になる。空は空と記録し、ノートに理由を書く。
- L592 — ★2026-09-02: highpass / bandpass_image は「0 を 0.5 に写した [0,1]」を 返す規約になった。以前は符号つき配列を image と称して返しており、 保存・段間 clip で負の半分 (画素の約 50%) が無言で 0 に潰れていた。 直ったことを推測でなく実測で残す: 最小値と負画素の割合。
- L727 — ★2026-09-02: estimate_noise は σ の単位で返るようになった (以前は σ>=0.08 で 1.0 に張り付き、3 倍違う σ に同じ値を返していた)。 直線 y=x を並べて「返り値が σ そのものか」を目で確かめられるようにする。
- L840 — ★_panel_grid のラベルは折り返さず、幅を超えると隣とぶつかって読めなく なる (tile 262px / font 19-17px なので 1 行 ≈ 全角 12 文字が限度)。 倍率の意味は表題と副題に逃がし、パネルには短い名前と数字だけ置く。
- L1184 — ★2026-09-02:
area_center は名前どおり (面積比, 行, 列) の 3 成分を返す ようになった (それまでは面積比 1 スカラだけで、中心を返していなかった)。 3 成分とも解像度に依らないよう [0,1] 正規化されているので、画素に戻すには 行 ×(H-1) / 列 ×(W-1)。ここでは戻した中心を絵に打って、返り値が本当に 中心であることを見て分かる形にする。
- L1712 — ★1 点ずつ apply_cmap を呼ぶと、その 1 点の中で正規化されて全部同じ色になる。 0..1 を張った LUT を 1 回だけ作り、そこから引く。
- L1950 — ★2026-09-02: gabor はカーネルの L1 ノルムで割る固定スケールになり、 op を跨いで比べられる絶対値を返すようになった。それまでは 「その画像での最大絶対値」で割っていたので、向きごとに別の除数で 割ることになり、応答の大小そのもの = 向きの識別力が潰れていた。 その代わり返り値は [0,1] のうち下端の狭い範囲 (この 3 模様では平均 0.007〜0.030) に収まるので、そのまま貼ると 3 枚とも真っ黒になる。 絵は 1〜99%tile で伸長して見せ、ラベルの数字は伸長前の実測値を出す (freq_sweep の highpass パネルと同じ約束)。
- L2065 — ★2026-09-02: 3 op は別実装になった。以前は 3 つとも geom “zoom” に相乗りで 相互の最大差が 0.0 / 4.9e-14(= 同一)、しかも 3 つとも b が死んでいた。 いまは zoom_image_factor=縦横 2 倍率 / zoom_image_size=目標サイズ / rescale_img=等方倍率 + 補間次数。キャンバス shape はどれも入力のまま。
- L411 — ★ 雑音は :func:
astrostack.noise_sigma(背景の頑健 σ)で測る。 「真値との残差 RMS」を使うとPSF のずれまで残差に入る —— この実験は わざとフレームごとに FWHM を変えているので、選び方を変えると合成後の PSF が変わり、残差が増えたのが雑音のせいなのか像が変わったせいなのか 区別できなくなる(実測でその値は 25.2 -> 61.3 と動いたが、その大半は 雑音ではなかった)。背景 σ は星の形に依らない。
- L471 — ★ 「最大差」は単一フレームでは動かない —— 再現率が 1 未満である限り、 見逃した 1 画素が最大値をそのまま押さえてしまうから。何画素が正解から 大きく外れたままかと外れの総量なら、除去の効き目がそのまま出る。
- L713 — ★ 原寸で並べると「2 個検出した」が目では確かめられない(44x44 の 中で 1.6 画素の対は数画素の塊にしかならない)。検出器の言い分だけを 信じさせる図にしないため、対の周りを同じ物理範囲だけ切って拡大する。
- L844 — ★ 誤差図は符号ではなく大きさを塗る。最初の版は発散配色で塗って いたが、この実験の誤差は常に正なので「正 = right の青」になり、 壊れている状態が「正しい」色で塗られるという逆の意味になった。 ここで読者に伝えたいのは向きではなく「どれだけ間違っているか」なので、 wrong の 1 色で濃さだけを変える(色だけに意味を載せないよう、 記号と数値も併記する)。
- L573 — 5. ★表現をまたいで一周(変換の連鎖こそが嘘の出る場所) # ————————————————————————— #
- L599 — ★「殻であって立体ではない」を 最大値投影で言ってはいけない —— MIP は奥行き方向の最大値なので、薄い殻でも中が詰まって見える(実際に一度 そう描いて「体積 5768 -> 殻 5608」というほとんど差の無い数字を出しかけた)。 中身が残っているかは 中心断面 と 内部の充填率 で言う。
- L896 — ★バーが張る像面の実寸。1.0 mm にしていたとき 208 標本 / mm = Nyquist 104 cyc/mm となり、200 cyc/mm のバーが 8 cyc/mm の太縞に化けていた (図が自分でエイリアスしていた)。0.25 mm なら 832 標本/mm、最高周波数 200 cyc/mm でも 1 周期 4.16 画素で足りる。
- L1151 — ★2 つの量を 1 枚の図に重ねると、尺度の取り方しだいで 2 本の曲線が 偶然ぴったり重なる(最初の版がまさにそうで、「独立な 2 軸」という主張の 真逆に見えていた)。尺度をいじって離すのは誤魔化しなので、パネルを縦に 分ける — 図の構造そのものが「別の軸だ」と言う。
- L1299 — ★ピークは行全体から取る。以前は
line[c - s : c + s + 1] と 書いていて、s が c を超えると 開始が負のインデックスになり、 Python が末尾 56 画素だけを切り出して 0.6167 を「ピーク」として返して いた(実際の最大は 0.9834)。正規化が崩れて曲線が 1.0 で頭打ちになり、 dip/peak も 1.9x Rayleigh で 0.0067 と誤って出ていた。
- L1581 — ★「ぼけ 1 画素以内」の範囲は格子から拾わない。掃引の刻みは 3.9 mm で、 被写界深度は 0.74 mm しかないので、格子には 1 点も入らない(最初の版は そこで min() が空になって落ちた)。二分法で境界そのものを解く。
- L1600 — ★誇張倍率は 縦の画素/mm ÷ 横の画素/mm。最初の版は逆数を書いていて、 8 倍に伸ばした図に「0.13 倍」と表示していた(読者に真逆を伝える)。
- L2090 — ★上下 2 段に分ける。1 枚に重ねると、単位の違う 2 本(画素数と検出率)が 同じ縦軸に乗っているように読めてしまう(実際そう見えていた)。
- L42 — ★ここを持たなかったあいだ、:func:
_called が (op 名 × example) の全組合せで :func:_strip_prose を呼び、そのたびに ast.parse + tokenize でソース全体を 解析し直していた。実測 2026-09-05: 2-D 881 op × 73 本 + 3-D 347 op × 118 本 + ledger 494 op × 73 本 = 約 14 万回のフルパースで、opdocs.py md 1 回に 10 分かかっていた(toc も html も同じ索引を作り直すのでフル再生成は 30 分級)。 散文落としはソースごとに 1 回あれば足りる ―― op 名に依存しないので。
- L105 — ★2026-09-08: ops1d(dsp 16 + funct1d 23)は登録済みなのに docs/ops に 1 枚もノートを持っていなかった —— OP_CATALOG には出るのに、op ごとの ノート(型契約・罠・関連 op)が無いので RAG コーパスから丸ごと欠けていた。
poc_web_roll_periodicity が dsp に 2 本足したときに気づいた。
- L790 — ★n-ary(多入力)層。2026-09-09 まで 17 op がノートを 1 枚も持っていなかった (
add_image sub_image bit_and reduce_domain union2 …)。OP_INDEX.json には tier=nary で載るのに docs/ops/ に無いので、RAG コーパスからは 永久に引けない状態だった。見落とした理由もはっきりしている: ここが ops.REGISTRY だけを歩いていて、ops.REGISTRY(899)と 2-D ノート(899)は 一致するので「欠落ゼロ」に見えた。層をまたいで数えて初めて出る (memory: feedback_search_all_tiers_before_declaring_a_gap)。 握り潰さない —— imgops_nary は numpy/scipy しか要らない一次モジュールで、 import に失敗するのは「壊れた checkout」であって「その環境に無い機能」ではない (imgevolve._all_ops が同じ理由で except を外している)。
- L832 — ★2026-09-07:
OPS3D[...]["doc"] は登録時に docstring の 1 行目だけ を切り出したもの(ops3d._build)。ノートの「使い方」にそれを使うと、 実装が何段落書いていても 1 行に化ける —— 「使い方が 1 行の op 494 本」 の 3-D ぶんはこの切り詰めが原因だった(docstring 自体は長い op が多数)。 台帳 dim と同じく関数の docstring を丸ごと読む。
- L855 — ★橋渡し op(
tb_<name>)は台帳の <name> と実装が同一で、例は台帳名で 書かれる。2026-09-06 まで 147 本が「例ゼロ」だったが、それは同じ実装を 呼ぶ例が別名で存在するのを数えていなかっただけ。台帳側の例を継承し、 ノートには「元 op の例」と明記する(嘘にならないように)。
- L1075 — ★n-ary(多入力)op は
fullseye.apply では呼べない —— あれは 1 画像 モデル。ここに 1 画像の呼び方を書くと、ノートが嘘をつく(この ノートの唯一の仕事は「どう呼ぶか」なので、それは無いより悪い)。 公開経路は fullseye.FullseyeGraph。
- L1094 — ★2026-09-07: 公開経路を先に書く。ここは実装モジュールの直 import しか 書いておらず、利用者が実際に使う
fullseye.ledger.<名> が出ていなかった (2-D 以外の 1,244 op すべて)。PoC が繰り返し「fs.<名> に無い」と報告して いたのは、名前が無いことではなく**入口が書かれていないこと**の問題だった。名>
- L1455 — ★入口は 6 言語で出す(2026-09-09)。葉(Studio の op ヘルプ)は 6 言語 10,191 ページあるのに、そこへ導く索引が日本語だけだった —— 訳は 在るのに辿り着けない、という形の欠落。枠の文言は
T() に載せるので、 対訳の穴は既存の門(test_chrome_translation_table_has_no_holes)が見る。
- L1500 — ★ここは長く
2d/guides/ だけを指していて、光学・PIV・トモグラフィ等 30 ファミリのガイドへ読み手を一度も送っていなかった(2026-09-09 修正)。
- L119 — ★
build/lib に前回の staging コピーが残っていると、setuptools はそれを そのまま wheel に詰める(2026-09-05 実測: py-modules から外したモジュールが wheel に入ったままで、門の変異テストが通ってしまった)。release.yml が clean checkout から建てる理由と同じ。ここでも建てる前に必ず捨てる。
- L313 — ★
--only suite を --full 無しで呼ぶと 0 項目になり、以前は 「すべて PASS」と言って rc=0 で帰っていた(2026-09-05 レビューで実測)。 何も検査していないのに通す門は、無い門より悪い。
- L54 — ★
tools/ の外にある唯一の生成物。だから取りこぼしていた —— 生成器を tools/*.py で探す限り、これは永久に見つからない。
- L77 — * ★そして危険: 生成直後の記事は画像を相対パスで書く。公開版は
raw.githubusercontent.com の絶対 URL に直したもの(Qiita は相対パスだと 画像が出ない —— memory feedback_qiita_svg_path_and_cache)。生成器だけを 回すと、その絶対 URL が 42 行ぶん巻き戻る。回すなら記事の公開手順まで 通しでやること。 除外はファイル名で書く。散文でまとめると(「wing*_gallery の 10 本」) 機械で照合できず、下の unclassified() が働かない。
- L167 — ★
tools/ の外にある生成物。tools/*.py を歩くだけでは永久に見つからない 位置にあり、実際 docs/OP_INDEX.json を取りこぼしていた。
typed_catalog.py
- L217 — ★ 既定値そのものが重い件は別扱い —— docstring に費用表を書き、 docs/KNOWN_ISSUES.md に「解いていない」として残した。ここで軽くするのは 検査を通すためであって、遅さを隠すためではない。 fourier_smooth(points, keep) の keep は既定が無い必須引数。束縛できないと 「引数が組めない」で永久にスキップされ、カバレッジ表には未到達として しか出ない(2026-09-06 の初回計測で 13 op 中この 1 本だけ落ちた)。 表面粗さ。制約は 2dx <= lambda_lo < lambda_hi <= ndx / 0<hurst<1 / sq>0 / n>=8。 サブピクセル計測。測定線の生成 op は入力を取らないので全引数にヒントが要る。
- L271 — ★ここを入れないと surface_params は毎回 fail-closed で拒否され、 カバレッジ 1 数字では「呼べた」に見えて実体は未実行になる。
- L459 — ★法線は軸に平行にしない。軸平行だと距離場が 1 軸にしか変化せず、 図の生成器が作る「スライスを並べた GIF」が 1 コマに潰れる(2026-09-08 実測)。 傾けた法線なら全スライスが変わる。長さは効かない(op が正規化する)ので、 正規化していないベクトルを渡してその仕様も見せる。
visionlab.py
- L53 — ★
float("50") は成功するので、float() を通すだけでは文字列が ミリメートルとして通り抜ける。visiondesign 側は弾くが、ここで先に float 化してしまうと その検証に届く前に数値になってしまう (敵対的検証で実測: VisionSystem(focal_mm=”50”) が通った)。 器の側でも同じ規律を持つ。
visualhull.py
- L123 — ★点が 1 つ残らず カメラ後方 = ほぼ確実に姿勢の規約違い(2026-09-08、 poc_livestock_body_volume が踏んだ)。この関数は OpenCV 規約(+Z 前方)を 要求するが、公開層で
look_at の名を持つのは render3d の gluLookAt 版 (−Z 前方の 4x4)。その M[:3,:3], M[:3,3] を渡すと全 voxel が後方判定に なり、例外なく空のシルエットが返って空の hull になる。黙って空を返すと 「彫り切った」と見分けが付かないので、ここだけは声を上げる(有効な場面 —— 物体が画角の後ろにある —— もあるので raise ではなく警告に留める)。
world_render.py
- L69 — ★
resolve() は実在しない場面に None を返す(資産が無い環境では正しい)。 検査せずに spec["xml"] を引くと TypeError: 'NoneType' object is not subscriptable という、原因を何も語らない例外になる —— 呼び手には 「何が無いのか」と「どう直すのか」を返す。
© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.