|
|
|
|
@ -28,20 +28,17 @@ logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(mess |
|
|
|
|
logger = logging.getLogger("recompute_svd") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def year_bounds(window_id: str) -> Tuple[str, str]: |
|
|
|
|
"""Return (start_date, end_date) for an annual window_id like '2024'. |
|
|
|
|
|
|
|
|
|
Quarterly window IDs (containing '-Q') are not supported — this script |
|
|
|
|
only processes annual windows. |
|
|
|
|
""" |
|
|
|
|
if "-Q" in window_id: |
|
|
|
|
raise ValueError( |
|
|
|
|
f"Quarterly window '{window_id}' is not supported. " |
|
|
|
|
"Only annual windows should be recomputed." |
|
|
|
|
) |
|
|
|
|
y = int(window_id) |
|
|
|
|
start = date(y, 1, 1).isoformat() |
|
|
|
|
end = date(y, 12, 31).isoformat() |
|
|
|
|
def quarter_bounds(window_id: str) -> Tuple[str, str]: |
|
|
|
|
# window_id like '2026-Q1' |
|
|
|
|
year, q = window_id.split("-Q") |
|
|
|
|
y = int(year) |
|
|
|
|
qn = int(q) |
|
|
|
|
starts = {1: (1, 1), 2: (4, 1), 3: (7, 1), 4: (10, 1)} |
|
|
|
|
ends = {1: (3, 31), 2: (6, 30), 3: (9, 30), 4: (12, 31)} |
|
|
|
|
s_m, s_d = starts[qn] |
|
|
|
|
e_m, e_d = ends[qn] |
|
|
|
|
start = date(y, s_m, s_d).isoformat() |
|
|
|
|
end = date(y, e_m, e_d).isoformat() |
|
|
|
|
return start, end |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -79,14 +76,12 @@ def main(argv: List[str] | None = None) -> int: |
|
|
|
|
db = MotionDatabase(dst) |
|
|
|
|
|
|
|
|
|
# find windows from original DB via trajectory helper |
|
|
|
|
all_window_ids = traj._load_window_ids(src) |
|
|
|
|
# Only process annual windows — quarterly windows are excluded from all PCA/SVD computation |
|
|
|
|
window_ids = [w for w in all_window_ids if "-Q" not in w] |
|
|
|
|
window_ids = traj._load_window_ids(src) |
|
|
|
|
if not window_ids: |
|
|
|
|
logger.error("No annual windows found in source DB %s", src) |
|
|
|
|
logger.error("No windows found in source DB %s", src) |
|
|
|
|
return 3 |
|
|
|
|
|
|
|
|
|
logger.info("Will recompute SVD for annual windows: %s", window_ids) |
|
|
|
|
logger.info("Will recompute SVD for windows: %s", window_ids) |
|
|
|
|
|
|
|
|
|
# clear existing svd_vectors rows for these windows in dst DB |
|
|
|
|
import duckdb |
|
|
|
|
@ -105,7 +100,7 @@ def main(argv: List[str] | None = None) -> int: |
|
|
|
|
|
|
|
|
|
# Run SVD per window |
|
|
|
|
for wid in window_ids: |
|
|
|
|
start, end = year_bounds(wid) |
|
|
|
|
start, end = quarter_bounds(wid) |
|
|
|
|
logger.info("Running SVD for %s (%s -> %s) k=%d", wid, start, end, args.k) |
|
|
|
|
res = run_svd_for_window( |
|
|
|
|
db=db, window_id=wid, start_date=start, end_date=end, k=args.k |
|
|
|
|
|