From e43f6b90438703589d9a16af4d4b12d05032c13b Mon Sep 17 00:00:00 2001 From: Peter Jacobson Date: Fri, 3 Jul 2026 00:00:30 +1000 Subject: [PATCH] Note feature-bank scale-blindness as a tracked TODO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cross-scan CLIP classification depends on a fixed 48px crop, so a banked entry's physical field of view depends on its source scan's resolution. CLIP embeddings are not scale invariant, so this silently degrades when pixel sizes differ across scans, with no way to detect the mismatch after the fact today. No behaviour change — just making this discoverable at the point where the fix would go (make_entry), found during a physics review while the bank schema is still young enough to extend cheaply. Co-Authored-By: Claude Sonnet 5 --- probeflow/analysis/feature_bank.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/probeflow/analysis/feature_bank.py b/probeflow/analysis/feature_bank.py index 4866ed6..7380d57 100644 --- a/probeflow/analysis/feature_bank.py +++ b/probeflow/analysis/feature_bank.py @@ -10,6 +10,14 @@ GUI-free and dependency-light (json + numpy only): the embeddings are produced by ``probeflow.analysis.features._embed_clip`` upstream and passed in as plain lists, so this module never imports torch/clip. + +KNOWN GAP (physics review 2026-07-02, not yet fixed): entries record no pixel +size, but crops are a fixed 48 px (see ``embed_particles_clip`` in +``probeflow.analysis.features``), so a banked sample's physical field of view +depends on its source scan's resolution. CLIP embeddings are not scale +invariant, so cross-scan classification is scale-blind and there is currently +no way to detect the mismatch after the fact. See ``make_entry`` below for +where to add the fix. """ from __future__ import annotations @@ -59,7 +67,14 @@ def make_entry( particle_index: int, bbox_px=None, ) -> dict: - """Build one bank entry (a labelled CLIP embedding + provenance).""" + """Build one bank entry (a labelled CLIP embedding + provenance). + + TODO(scale-blind bank, see module docstring): while the schema is still + young (``BANK_SCHEMA_VERSION`` above), consider adding the source scan's + pixel size (or the crop's physical size in nm) here so Phase-2 + classification can warn on or weight by a scale mismatch between the bank + entry and the particle being classified. + """ return { "class_name": str(class_name), "embedding": [float(x) for x in np.asarray(embedding, dtype=float).ravel()],