update filter, flow ema 0.5 + med 3

This commit is contained in:
ykcheungab
2026-09-12 19:36:36 +08:00
parent 5f78115429
commit 0d5d8ff70d
12 changed files with 697 additions and 62 deletions
+35 -4
View File
@@ -242,7 +242,9 @@ class Calibration:
meta: dict[str, Any] = {}
meta.update(self.provenance)
meta.update({k: v for k, v in self.identity.items() if k not in meta})
for key in ("stitch_resolution", "dis_mode", "hhd_downsample", "config_ref"):
for key in ("stitch_resolution", "dis_mode", "hhd_downsample",
"flow_ema_alpha", "force_median_window", "force_lowpass_cutoff_hz",
"config_ref"):
if key in self.pipeline and self.pipeline[key] is not None:
meta[key] = self.pipeline[key]
if self.measurements:
@@ -387,7 +389,8 @@ def check(doc: dict | Calibration, *, pipeline: dict | None = None) -> CheckResu
warns.append("empty sn on factory calibration")
if pipeline is not None and isinstance(doc, Calibration):
for key in ("stitch_resolution", "dis_mode", "hhd_downsample"):
for key in ("stitch_resolution", "dis_mode", "hhd_downsample",
"flow_ema_alpha", "force_median_window", "force_lowpass_cutoff_hz"):
if key in doc.pipeline and key in pipeline and doc.pipeline[key] != pipeline[key]:
warns.append(f"pipeline mismatch: {key}")
@@ -601,11 +604,14 @@ def load(
def pipeline_from_sensor_json(path: str | Path | None) -> dict[str, Any]:
"""Pull stitch / tracker fields from a sensor.json for export pipeline/meta."""
"""Pull stitch / tracker / filter fields from a sensor.json for export pipeline/meta."""
pipeline: dict[str, Any] = {
"stitch_resolution": None,
"dis_mode": None,
"hhd_downsample": None,
"flow_ema_alpha": None,
"force_median_window": None,
"force_lowpass_cutoff_hz": None,
"config_ref": None,
}
if path is None:
@@ -622,6 +628,7 @@ def pipeline_from_sensor_json(path: str | Path | None) -> dict[str, Any]:
return pipeline
camera = data.get("camera") if isinstance(data.get("camera"), dict) else {}
tracker = data.get("tracker") if isinstance(data.get("tracker"), dict) else {}
filters = data.get("filters") if isinstance(data.get("filters"), dict) else {}
stitch = camera.get("resolution_stitch")
if isinstance(stitch, (list, tuple)) and len(stitch) >= 2:
pipeline["stitch_resolution"] = [int(stitch[0]), int(stitch[1])]
@@ -635,6 +642,29 @@ def pipeline_from_sensor_json(path: str | Path | None) -> dict[str, Any]:
pipeline["hhd_downsample"] = int(tracker["hhd_downsample"])
except (TypeError, ValueError):
pipeline["hhd_downsample"] = tracker.get("hhd_downsample")
# Signal-conditioning settings change the reported force values, so they
# belong to the pipeline identity just like dis_mode / hhd_downsample.
if filters:
enabled = bool(filters.get("enabled", True))
for key in ("flow_ema_alpha", "force_lowpass_cutoff_hz"):
if key in filters:
try:
pipeline[key] = float(filters[key]) if enabled else 0.0
except (TypeError, ValueError):
pipeline[key] = filters.get(key)
elif key == "flow_ema_alpha":
pipeline[key] = 0.5 if enabled else 0.0
else:
pipeline[key] = 10.0 if enabled else 0.0
if "force_median_window" in filters:
try:
pipeline["force_median_window"] = (
int(filters["force_median_window"]) if enabled else 1
)
except (TypeError, ValueError):
pipeline["force_median_window"] = filters.get("force_median_window")
else:
pipeline["force_median_window"] = 3 if enabled else 1
return pipeline
@@ -717,7 +747,8 @@ def build(
for k, v in extra_meta.items():
if k == "samples":
continue
if k in ("stitch_resolution", "dis_mode", "hhd_downsample", "config_ref"):
if k in ("stitch_resolution", "dis_mode", "hhd_downsample", "config_ref",
"flow_ema_alpha", "force_median_window", "force_lowpass_cutoff_hz"):
if k not in pipeline or pipeline[k] is None:
pipeline[k] = v
elif k in ("sensor_type", "sn", "hardware_rev", "gel_id"):