chore(webui): remove timeline animation page
The animated t-SNE 'embedding landscape' added no real analytical value and its cumulative-by-month logic was inherently confusing (ancient drafts appearing late in the animation). Removed entirely rather than maintained. Drops the /timeline route, template, nav link, data builder (get_timeline_animation_data / _compute_timeline_animation_data) and its test. The Overview mini-timeline and /api/timeline (separate features) are untouched.
This commit is contained in:
@@ -69,7 +69,6 @@ from webui.data.analysis import ( # noqa: F401
|
||||
get_timeline_data,
|
||||
get_similarity_graph,
|
||||
get_idea_clusters,
|
||||
get_timeline_animation_data,
|
||||
get_monitor_status,
|
||||
get_citation_graph,
|
||||
get_landscape_tsne,
|
||||
|
||||
@@ -502,81 +502,6 @@ def _compute_idea_clusters(db: Database) -> dict:
|
||||
"empty": False,
|
||||
}
|
||||
|
||||
def get_timeline_animation_data(db: Database) -> dict:
|
||||
"""Timeline animation (cached for 5 min)."""
|
||||
return _cached("timeline_animation", lambda: _compute_timeline_animation_data(db))
|
||||
|
||||
def _compute_timeline_animation_data(db: Database) -> dict:
|
||||
"""Compute t-SNE on all drafts, return points with month info + category_monthly.
|
||||
|
||||
t-SNE is computed once on ALL drafts so coordinates are stable across
|
||||
animation frames. Each point carries a ``month`` field (YYYY-MM) so the
|
||||
front-end can build cumulative animation frames.
|
||||
"""
|
||||
|
||||
|
||||
embeddings = db.all_embeddings()
|
||||
if len(embeddings) < 5:
|
||||
return {"points": [], "months": [], "category_monthly": {}}
|
||||
|
||||
pairs = db.drafts_with_ratings(limit=1000)
|
||||
rating_map = {d.name: r for d, r in pairs}
|
||||
draft_map = {d.name: d for d, _ in pairs}
|
||||
|
||||
# Filter to drafts that have both embeddings and ratings
|
||||
names = [n for n in embeddings if n in rating_map]
|
||||
if len(names) < 5:
|
||||
return {"points": [], "months": [], "category_monthly": {}}
|
||||
|
||||
matrix = np.array([embeddings[n] for n in names])
|
||||
|
||||
try:
|
||||
tsne = TSNE(n_components=2, perplexity=min(30, len(names) - 1),
|
||||
random_state=42, max_iter=500)
|
||||
coords = tsne.fit_transform(matrix)
|
||||
except Exception:
|
||||
return {"points": [], "months": [], "category_monthly": {}}
|
||||
|
||||
# Build points with month
|
||||
points = []
|
||||
month_set: set[str] = set()
|
||||
category_monthly: dict[str, dict[str, int]] = defaultdict(lambda: defaultdict(int))
|
||||
|
||||
for i, name in enumerate(names):
|
||||
r = rating_map[name]
|
||||
d = draft_map.get(name)
|
||||
month = _extract_month(d.time if d else None)
|
||||
if month == "unknown":
|
||||
continue # Undated docs (e.g. ISO/ETSI) can't be placed on a temporal animation
|
||||
cat = r.categories[0] if r.categories else "Other"
|
||||
month_set.add(month)
|
||||
category_monthly[month][cat] += 1
|
||||
points.append({
|
||||
"name": name,
|
||||
"title": d.title if d else name,
|
||||
"x": round(float(coords[i, 0]), 3),
|
||||
"y": round(float(coords[i, 1]), 3),
|
||||
"category": cat,
|
||||
"score": round(r.composite_score, 2),
|
||||
"month": month,
|
||||
})
|
||||
|
||||
# Deliver points in chronological order so the front-end's cumulative
|
||||
# filter (p.month <= frame) is append-only. Otherwise new points get
|
||||
# inserted mid-array and Plotly's index-based frame transition animates
|
||||
# existing markers flying to other drafts' coordinates ("jumping points").
|
||||
points.sort(key=lambda p: (p["month"], p["name"]))
|
||||
|
||||
months = sorted(month_set)
|
||||
# Convert defaultdict to plain dict for JSON
|
||||
cat_monthly_plain = {m: dict(cats) for m, cats in category_monthly.items()}
|
||||
|
||||
return {
|
||||
"points": points,
|
||||
"months": months,
|
||||
"category_monthly": cat_monthly_plain,
|
||||
}
|
||||
|
||||
def get_monitor_status(db: Database) -> MonitorStatus:
|
||||
"""Return monitoring status data for dashboard."""
|
||||
runs = db.get_monitor_runs(limit=20)
|
||||
|
||||
Reference in New Issue
Block a user