fix fish weight calculation by using correct parameters. output video
This commit is contained in:
@@ -13,7 +13,7 @@ import shutil
|
||||
import sqlite3
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
from typing import Any, Optional, Set, Tuple
|
||||
from typing import Any, Dict, List, Optional, Set, Tuple
|
||||
|
||||
from app.settings import Settings
|
||||
from app.state import HealthSnapshot, MeasureSnapshot
|
||||
@@ -87,9 +87,14 @@ def init_db(settings: Settings) -> None:
|
||||
video_right TEXT NOT NULL DEFAULT '',
|
||||
error TEXT,
|
||||
raw_prediction_path TEXT,
|
||||
source_path TEXT
|
||||
source_path TEXT,
|
||||
client_id TEXT DEFAULT NULL,
|
||||
pred REAL,
|
||||
star INTEGER DEFAULT 0
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_measure_client_id ON measure_snapshots(client_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS health_snapshots (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
created_at TEXT NOT NULL,
|
||||
@@ -116,10 +121,59 @@ def init_db(settings: Settings) -> None:
|
||||
)
|
||||
_migrate_delivery_cursor_from_legacy(conn)
|
||||
_ensure_delivery_cursors(conn)
|
||||
_migrate_add_client_id_column(conn)
|
||||
_migrate_add_pred_star_columns(conn)
|
||||
_migrate_add_calculation_log_column(conn)
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
def _migrate_add_client_id_column(conn: sqlite3.Connection) -> None:
|
||||
"""为旧数据库添加 client_id 列(如果不存在)。"""
|
||||
row = conn.execute(
|
||||
"SELECT name FROM sqlite_master WHERE type='table' AND name='measure_snapshots'"
|
||||
).fetchone()
|
||||
if row is None:
|
||||
return
|
||||
# 检查 client_id 列是否存在
|
||||
cols = conn.execute("PRAGMA table_info(measure_snapshots)").fetchall()
|
||||
has_client_id = any(col[1] == "client_id" for col in cols)
|
||||
if not has_client_id:
|
||||
conn.execute("ALTER TABLE measure_snapshots ADD COLUMN client_id TEXT DEFAULT NULL")
|
||||
conn.execute("CREATE INDEX idx_measure_client_id ON measure_snapshots(client_id)")
|
||||
conn.commit()
|
||||
|
||||
|
||||
def _migrate_add_pred_star_columns(conn: sqlite3.Connection) -> None:
|
||||
"""为旧数据库添加 pred 和 star 列(如果不存在)。"""
|
||||
row = conn.execute(
|
||||
"SELECT name FROM sqlite_master WHERE type='table' AND name='measure_snapshots'"
|
||||
).fetchone()
|
||||
if row is None:
|
||||
return
|
||||
cols = conn.execute("PRAGMA table_info(measure_snapshots)").fetchall()
|
||||
col_names = {col[1] for col in cols}
|
||||
if "pred" not in col_names:
|
||||
conn.execute("ALTER TABLE measure_snapshots ADD COLUMN pred REAL")
|
||||
if "star" not in col_names:
|
||||
conn.execute("ALTER TABLE measure_snapshots ADD COLUMN star INTEGER DEFAULT 0")
|
||||
conn.commit()
|
||||
|
||||
|
||||
def _migrate_add_calculation_log_column(conn: sqlite3.Connection) -> None:
|
||||
"""为旧数据库添加 calculation_log 列(体重推算过程文本,对齐 test_dgcnn 终端输出)。"""
|
||||
row = conn.execute(
|
||||
"SELECT name FROM sqlite_master WHERE type='table' AND name='measure_snapshots'"
|
||||
).fetchone()
|
||||
if row is None:
|
||||
return
|
||||
cols = conn.execute("PRAGMA table_info(measure_snapshots)").fetchall()
|
||||
col_names = {col[1] for col in cols}
|
||||
if "calculation_log" not in col_names:
|
||||
conn.execute("ALTER TABLE measure_snapshots ADD COLUMN calculation_log TEXT")
|
||||
conn.commit()
|
||||
|
||||
|
||||
def _migrate_delivery_cursor_from_legacy(conn: sqlite3.Connection) -> None:
|
||||
"""旧表 delivery_cursor(kind) → delivery_client_cursor(default, kind)。"""
|
||||
row = conn.execute(
|
||||
@@ -172,6 +226,7 @@ def save_measure_snapshot(
|
||||
settings: Settings,
|
||||
snap: MeasureSnapshot,
|
||||
source_path: Optional[str] = None,
|
||||
client_id: Optional[str] = None,
|
||||
) -> None:
|
||||
init_db(settings)
|
||||
conn = _connect(settings.sqlite_path)
|
||||
@@ -185,8 +240,9 @@ def save_measure_snapshot(
|
||||
"""
|
||||
INSERT INTO measure_snapshots (
|
||||
created_at, result_json, video_left, video_right,
|
||||
error, raw_prediction_path, source_path
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
error, raw_prediction_path, source_path, client_id, pred, star,
|
||||
calculation_log
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
""",
|
||||
(
|
||||
ts,
|
||||
@@ -196,6 +252,10 @@ def save_measure_snapshot(
|
||||
snap.error,
|
||||
snap.raw_prediction_path,
|
||||
source_path,
|
||||
client_id,
|
||||
snap.pred,
|
||||
1 if snap.star else 0,
|
||||
snap.calculation_log,
|
||||
),
|
||||
)
|
||||
finally:
|
||||
@@ -251,7 +311,7 @@ def get_latest_measure(settings: Settings) -> MeasureSnapshot:
|
||||
row = conn.execute(
|
||||
"""
|
||||
SELECT created_at, result_json, video_left, video_right,
|
||||
error, raw_prediction_path
|
||||
error, raw_prediction_path, calculation_log
|
||||
FROM measure_snapshots
|
||||
ORDER BY id DESC
|
||||
LIMIT 1
|
||||
@@ -269,11 +329,53 @@ def get_latest_measure(settings: Settings) -> MeasureSnapshot:
|
||||
updated_at=_parse_dt(row["created_at"]),
|
||||
error=row["error"],
|
||||
raw_prediction_path=row["raw_prediction_path"],
|
||||
calculation_log=row["calculation_log"],
|
||||
)
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
def list_all_measure_snapshots(settings: Settings) -> List[Dict[str, Any]]:
|
||||
"""返回 ``measure_snapshots`` 全部行(id 降序,最新在前),供调试接口使用。"""
|
||||
init_db(settings)
|
||||
conn = _connect(settings.sqlite_path)
|
||||
try:
|
||||
rows = conn.execute(
|
||||
"""
|
||||
SELECT id, created_at, result_json, video_left, video_right,
|
||||
error, raw_prediction_path, source_path, client_id, pred, star,
|
||||
calculation_log
|
||||
FROM measure_snapshots
|
||||
ORDER BY id DESC
|
||||
"""
|
||||
).fetchall()
|
||||
out: List[Dict[str, Any]] = []
|
||||
for row in rows:
|
||||
data: Any = json.loads(row["result_json"])
|
||||
if not isinstance(data, list):
|
||||
data = []
|
||||
st = row["star"]
|
||||
out.append(
|
||||
{
|
||||
"id": row["id"],
|
||||
"created_at": row["created_at"],
|
||||
"result": data,
|
||||
"video_left": row["video_left"] or "",
|
||||
"video_right": row["video_right"] or "",
|
||||
"error": row["error"],
|
||||
"raw_prediction_path": row["raw_prediction_path"],
|
||||
"source_path": row["source_path"],
|
||||
"client_id": row["client_id"],
|
||||
"pred": row["pred"],
|
||||
"star": bool(st) if st is not None else False,
|
||||
"calculation_log": row["calculation_log"],
|
||||
}
|
||||
)
|
||||
return out
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
def get_latest_health(settings: Settings) -> HealthSnapshot:
|
||||
init_db(settings)
|
||||
conn = _connect(settings.sqlite_path)
|
||||
@@ -412,7 +514,10 @@ def pop_next_measure(
|
||||
settings: Settings,
|
||||
client_id: str = DEFAULT_CLIENT_ID,
|
||||
) -> Tuple[MeasureSnapshot, bool, Optional[int]]:
|
||||
"""取该客户端队首未投递且可交付的 measure 快照并推进其游标;跳过不可交付行仅推进游标。"""
|
||||
"""取该客户端队首未投递且可交付的 measure 快照并推进其游标;跳过不可交付行仅推进游标。
|
||||
|
||||
只返回与该 client_id 匹配的记录(client_id 为 NULL 的记录对所有客户端可见,用于向后兼容)。
|
||||
"""
|
||||
cid = normalize_client_id(client_id)
|
||||
init_db(settings)
|
||||
conn = _connect(settings.sqlite_path)
|
||||
@@ -421,16 +526,17 @@ def pop_next_measure(
|
||||
last_id = _last_delivered_id(conn, "measure", "measure_snapshots", cid)
|
||||
|
||||
while True:
|
||||
# 只查询匹配该 client_id 或 client_id 为 NULL 的记录
|
||||
next_row = conn.execute(
|
||||
"""
|
||||
SELECT id, created_at, result_json, video_left, video_right,
|
||||
error, raw_prediction_path
|
||||
error, raw_prediction_path, pred, star, calculation_log
|
||||
FROM measure_snapshots
|
||||
WHERE id > ?
|
||||
WHERE id > ? AND (client_id = ? OR client_id IS NULL)
|
||||
ORDER BY id ASC
|
||||
LIMIT 1
|
||||
""",
|
||||
(last_id,),
|
||||
(last_id, cid),
|
||||
).fetchone()
|
||||
|
||||
if next_row is None:
|
||||
@@ -463,6 +569,9 @@ def pop_next_measure(
|
||||
updated_at=_parse_dt(next_row["created_at"]),
|
||||
error=err,
|
||||
raw_prediction_path=next_row["raw_prediction_path"],
|
||||
pred=next_row["pred"],
|
||||
star=bool(next_row["star"]) if next_row["star"] is not None else False,
|
||||
calculation_log=next_row["calculation_log"],
|
||||
)
|
||||
return snap, True, nid
|
||||
except Exception:
|
||||
@@ -592,6 +701,20 @@ def add_watch_processed(settings: Settings, path: str, kind: str) -> None:
|
||||
conn.close()
|
||||
|
||||
|
||||
def _safe_rm_tree(path: Path) -> None:
|
||||
"""安全删除目录树(包括目录本身),忽略不存在或权限错误。"""
|
||||
p = Path(path).resolve()
|
||||
if not p.exists():
|
||||
return
|
||||
try:
|
||||
if p.is_dir():
|
||||
shutil.rmtree(p)
|
||||
else:
|
||||
p.unlink()
|
||||
except OSError as e:
|
||||
print(f"[prestart-fresh] skip remove {p}: {e}", flush=True)
|
||||
|
||||
|
||||
def clear_runtime_compute_dirs(settings: Settings) -> None:
|
||||
"""清空 FishMeasure / FishAction 运行时目录、托管预览、ingest 临时文件(保留目录本身)。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user