Picker: render existing annotation as a clickable mark below the video

When a video that already has a barrier_opening row is loaded, a thin
bar now appears below the player with a red vertical line at the
marked opening_s. A tooltip shows the timestamp, the analyst's
initials, and the bad_rois flag. Clicking the line snaps the player
to the exact opening; clicking elsewhere on the bar seeks
proportionally. Bar is hidden for un-annotated videos.

API change: each queue item now carries an `existing` field with the
opening_s, bad_rois, analyst, etc. from barrier_opening.csv when
available, so the frontend can paint the mark without extra requests.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Giorgio Gilestro 2026-05-01 14:27:33 +01:00
parent 2623df4172
commit d0f0e2d443
2 changed files with 83 additions and 5 deletions

View file

@ -73,6 +73,7 @@ class QueueItem:
duration_s: float | None
done: bool
metadata: dict # experimental fields aggregated from the merged TSV
existing: dict | None # current barrier_opening.csv row if already picked
# ─── Queue building ─────────────────────────────────────────────────────
@ -142,13 +143,19 @@ def _build_queue() -> list[QueueItem]:
"duration_s": float(r.duration_s) if pd.notna(r.duration_s) else None,
}
existing_by_key: dict[tuple[str, str, str], dict] = {}
if OUTPUT_CSV.exists():
out = pd.read_csv(OUTPUT_CSV)
done_keys = set(zip(out["machine_name"],
out["session_date"],
out["session_time"]))
else:
done_keys = set()
for _, r in out.iterrows():
key = (r["machine_name"], r["session_date"], r["session_time"])
existing_by_key[key] = {
"opening_s": float(r["opening_s"]) if pd.notna(r["opening_s"]) else None,
"trim_first_s": int(r["trim_first_s"]) if pd.notna(r.get("trim_first_s")) else 0,
"bad_rois": str(r.get("bad_rois", "") or "") if pd.notna(r.get("bad_rois")) else "",
"analyst": str(r.get("analyst", "") or "") if pd.notna(r.get("analyst")) else "",
"notes": str(r.get("notes", "") or "") if pd.notna(r.get("notes")) else "",
}
done_keys = set(existing_by_key)
seen: set[tuple[str, str, str]] = set()
items: list[QueueItem] = []
@ -189,6 +196,7 @@ def _build_queue() -> list[QueueItem]:
duration_s=inv_row["duration_s"],
done=key in done_keys,
metadata=metadata,
existing=existing_by_key.get(key),
))
return items
@ -217,6 +225,7 @@ async def get_queue() -> JSONResponse:
"duration_s": q.duration_s,
"done": q.done,
"metadata": q.metadata,
"existing": q.existing,
}
for q in queue
])