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:
parent
2623df4172
commit
d0f0e2d443
2 changed files with 83 additions and 5 deletions
|
|
@ -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
|
||||
])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue