AsianPlayer/TriDrive / code /data /qc_driver_box_suspects.py
AsianPlayer's picture
download
raw
4.57 kB
"""cwm3/data/qc_driver_box_suspects.py — per-route agreement of the causal kinematics with the old non-causal cache and the list of
wrong-occupant suspects (route-level causal box locked onto a co-occupant). For a given kin dir (+ pose dirs, v2 first):
per route (>= 500 jointly valid cells): Pearson r of head_turn and min_hand_rest_dist (K, old vs new), hands_on agreement, co-occupant
fraction, driver-side-prior source. Suspect = r(head_turn) < 0.3 or hands_on agreement < 0.5. Writes <kin_dir>/qc_per_route.csv and
<kin_dir>/driver_box_suspect_routes.json (summary per split: routes/anchors flagged), prints the summary."""
import argparse, json, sys
from pathlib import Path
import numpy as np, pandas as pd
ROOT = Path(__file__).resolve().parents[1]; OLD = ROOT.parent / "cwm2" / "results" / "targets_kin"; S12 = ROOT.parent / "s12_wm" / "results"
def main():
ap = argparse.ArgumentParser(); ap.add_argument("--kin-dir", default=str(ROOT / "results" / "targets_kin_causal_routes")); ap.add_argument("--pose-dirs", nargs="*", default=[str(ROOT / "results" / "pose_causal_routes")]); a = ap.parse_args()
KIN = Path(a.kin_dir); pdirs = [Path(d) for d in a.pose_dirs]
def pose(u):
for d in pdirs:
if (d / f"{u}.npz").exists(): return np.load(d / f"{u}.npz"), d.name
return None, None
rows = []
for reg in ("manual", "engaged"):
for sp in ("train", "val", "test"):
o = np.load(OLD / f"kin_{reg}_{sp}.npz", allow_pickle=True); n = np.load(KIN / f"kin_causal_{reg}_{sp}.npz", allow_pickle=True)
uid = n["uid"]; both = n["Kvalid"] & o["Kvalid"]; Ko = o["K"][:, :, [6, 10]].astype(np.float32); Kn = n["K_c"][:, :, [6, 10]].astype(np.float32); So, Sn = o["S"][:, :, 0], n["S_c"][:, :, 0]
order = np.argsort(uid, kind="stable"); b = np.flatnonzero(np.r_[1, uid[order][1:] != uid[order][:-1], 1])
for a_, e_ in zip(b[:-1], b[1:]):
rr = order[a_:e_]; u = uid[rr[0]]; m = both[rr]; n_anch = len(rr)
if m.sum() < 500: continue
z, src_dir = pose(u)
if z is None: continue
def pr(c):
x, y = Ko[rr][:, :, c][m], Kn[rr][:, :, c][m]; k = np.isfinite(x) & np.isfinite(y)
return float(np.corrcoef(x[k], y[k])[0, 1]) if k.sum() > 100 and x[k].std() > 0 and y[k].std() > 0 else np.nan
ms = np.isfinite(So[rr]) & np.isfinite(Sn[rr]); agr = float((So[rr][ms] == Sn[rr][ms]).mean()) if ms.any() else np.nan
rows.append(dict(reg=reg, sp=sp, uid=u, src=str(z["dside_source"]), pose_dir=src_dir, r_ht=pr(0), r_md=pr(1), hands_agr=agr, n_cells=int(m.sum()), n_anchors=n_anch, co_frac=float((z["n_persons"] >= 2).mean())))
df = pd.DataFrame(rows); df.to_csv(KIN / "qc_per_route.csv", index=False)
sus = df[(df.r_ht < 0.3) | (df.hands_agr < 0.5)]
tot = {}
for reg in ("manual", "engaged"):
for sp in ("train", "val", "test"): tot[(reg, sp)] = int(len(np.load(S12 / f"targets_{reg}_{sp}.npz", allow_pickle=True)["t"]))
summ = {f"{r}_{s}": dict(routes_compared=int(((df.reg == r) & (df.sp == s)).sum()), routes_flagged=int(((sus.reg == r) & (sus.sp == s)).sum()), anchors_flagged=int(sus[(sus.reg == r) & (sus.sp == s)].n_anchors.sum()), anchors_total=tot[(r, s)],
anchors_flagged_frac=round(float(sus[(sus.reg == r) & (sus.sp == s)].n_anchors.sum() / tot[(r, s)]), 4), median_r_head_turn=round(float(df[(df.reg == r) & (df.sp == s)].r_ht.median()), 3)) for r in ("manual", "engaged") for s in ("train", "test")}
by_src = df.groupby("src").agg(routes=("uid", "count"), median_r_head_turn=("r_ht", "median"), median_hands_agr=("hands_agr", "median"), co_frac_mean=("co_frac", "mean"), flagged=("r_ht", lambda x: int((x < 0.3).sum()))).round(3).reset_index().to_dict("records")
rec = dict(kin_dir=str(KIN), pose_dirs=[str(d) for d in pdirs], definition="suspect = per-route r(head_turn) < 0.3 or hands_on agreement < 0.5 on >= 500 jointly valid cells", summary=summ, n_routes_flagged=int(len(sus.uid.unique())), by_source=by_src,
flagged=sus.sort_values("n_anchors", ascending=False)[["reg", "sp", "uid", "src", "pose_dir", "r_ht", "r_md", "hands_agr", "co_frac", "n_anchors"]].round(3).to_dict("records"))
(KIN / "driver_box_suspect_routes.json").write_text(json.dumps(rec, indent=1))
print("SUSPECTS_DONE", json.dumps(dict(n_routes_flagged=rec["n_routes_flagged"], summary=summ, by_source=by_src), default=str))
if __name__ == "__main__":
main()

Xet Storage Details

Size:
4.57 kB
·
Xet hash:
0cf7260e4bd47e78b567e1abd78d55aca498bef8ddab4e18d7db7a32c098caa4

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.