Major changes in annotation and results showing/storing
This commit is contained in:
@@ -105,6 +105,103 @@ class DatabaseManager:
|
||||
conn.execute("PRAGMA foreign_keys = ON") # Enable foreign keys
|
||||
return conn
|
||||
|
||||
# ==================== Detection Run Operations ====================
|
||||
|
||||
def upsert_detection_run(
|
||||
self,
|
||||
image_id: int,
|
||||
model_id: int,
|
||||
count: int,
|
||||
metadata: Optional[Dict] = None,
|
||||
) -> bool:
|
||||
"""Insert/update a per-image per-model detection run summary.
|
||||
|
||||
This enables the UI to show runs even when zero detections were produced.
|
||||
"""
|
||||
|
||||
conn = self.get_connection()
|
||||
try:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute(
|
||||
"""
|
||||
INSERT INTO detection_runs (image_id, model_id, detected_at, count, metadata)
|
||||
VALUES (?, ?, CURRENT_TIMESTAMP, ?, ?)
|
||||
ON CONFLICT(image_id, model_id) DO UPDATE SET
|
||||
detected_at = CURRENT_TIMESTAMP,
|
||||
count = excluded.count,
|
||||
metadata = excluded.metadata
|
||||
""",
|
||||
(
|
||||
int(image_id),
|
||||
int(model_id),
|
||||
int(count),
|
||||
json.dumps(metadata) if metadata else None,
|
||||
),
|
||||
)
|
||||
conn.commit()
|
||||
return True
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def get_detection_run_summaries(self, limit: int = 500, offset: int = 0) -> List[Dict]:
|
||||
"""Return latest detection run summaries grouped by image+model.
|
||||
|
||||
Includes runs with 0 detections.
|
||||
"""
|
||||
|
||||
conn = self.get_connection()
|
||||
try:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute(
|
||||
"""
|
||||
SELECT
|
||||
dr.image_id,
|
||||
dr.model_id,
|
||||
dr.detected_at,
|
||||
dr.count,
|
||||
dr.metadata,
|
||||
i.relative_path AS image_path,
|
||||
i.filename AS image_filename,
|
||||
m.model_name,
|
||||
m.model_version,
|
||||
GROUP_CONCAT(DISTINCT d.class_name) AS classes
|
||||
FROM detection_runs dr
|
||||
JOIN images i ON dr.image_id = i.id
|
||||
JOIN models m ON dr.model_id = m.id
|
||||
LEFT JOIN detections d
|
||||
ON d.image_id = dr.image_id AND d.model_id = dr.model_id
|
||||
GROUP BY dr.image_id, dr.model_id
|
||||
ORDER BY dr.detected_at DESC
|
||||
LIMIT ? OFFSET ?
|
||||
""",
|
||||
(int(limit), int(offset)),
|
||||
)
|
||||
|
||||
rows: List[Dict] = []
|
||||
for row in cursor.fetchall():
|
||||
item = dict(row)
|
||||
if item.get("metadata"):
|
||||
try:
|
||||
item["metadata"] = json.loads(item["metadata"])
|
||||
except Exception:
|
||||
item["metadata"] = None
|
||||
rows.append(item)
|
||||
return rows
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def get_detection_run_total(self) -> int:
|
||||
"""Return total number of detection_runs rows."""
|
||||
|
||||
conn = self.get_connection()
|
||||
try:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT COUNT(*) AS cnt FROM detection_runs")
|
||||
row = cursor.fetchone()
|
||||
return int(row["cnt"] if row and row["cnt"] is not None else 0)
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
# ==================== Model Operations ====================
|
||||
|
||||
def add_model(
|
||||
@@ -527,6 +624,14 @@ class DatabaseManager:
|
||||
conn = self.get_connection()
|
||||
try:
|
||||
cursor = conn.cursor()
|
||||
# Also clear detection run summaries so the Results tab does not continue
|
||||
# to show historical runs after detections have been wiped.
|
||||
try:
|
||||
cursor.execute("DELETE FROM detection_runs")
|
||||
except sqlite3.OperationalError:
|
||||
# Backwards-compatible: table may not exist on older DB files.
|
||||
pass
|
||||
|
||||
cursor.execute("DELETE FROM detections")
|
||||
conn.commit()
|
||||
return cursor.rowcount
|
||||
|
||||
Reference in New Issue
Block a user