forked from mergeos-bounties/Loru
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgen_unique_pack.py
More file actions
74 lines (59 loc) · 2.2 KB
/
Copy pathgen_unique_pack.py
File metadata and controls
74 lines (59 loc) · 2.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
"""Generate a deterministic, gloss-specific unique landmark pack.
Usage:
python scripts/gen_unique_pack.py --gloss work --cycle 2026-07-18a --out data/samples/work.json
Implements the documented unique-frame rule:
seed = sha256("demo-asl:{gloss}:{cycle_id}").hexdigest()[0:8]
phase = int(seed, 16) / 0xffffffff
then feeds `phase` into the synthetic spiral generator so each gloss gets a
repeatable but distinct landmark trajectory (no cloned/renamed frames).
"""
from __future__ import annotations
import argparse
import hashlib
import json
import math
from pathlib import Path
JOINTS = 21
FRAMES = 16
def phase_for(gloss: str, cycle_id: str) -> float:
seed = hashlib.sha256(f"demo-asl:{gloss}:{cycle_id}".encode()).hexdigest()[0:8]
return int(seed, 16) / 0xFFFFFF
def unique_frames(gloss: str, cycle_id: str, frames: int = FRAMES, joints: int = JOINTS) -> list:
phase = phase_for(gloss, cycle_id)
seq = []
for f in range(frames):
t = f / max(1, frames - 1)
frame = []
for j in range(joints):
ang = t * math.pi * 2 + j * 0.15 + phase * math.pi * 2
frame.append(
[
round(0.5 + 0.2 * math.cos(ang), 6),
round(0.5 + 0.2 * math.sin(ang), 6),
round(0.02 * math.sin(ang * 2), 6),
]
)
seq.append(frame)
return seq
def build(gloss: str, cycle_id: str) -> dict:
return {
"gloss": gloss,
"language": "demo-asl",
"fps": 15,
"source": f"synthetic-unique-{cycle_id.split('-')[-1]}",
"frames": unique_frames(gloss, cycle_id),
"extractor": "unique-synthetic",
}
def main() -> None:
ap = argparse.ArgumentParser()
ap.add_argument("--gloss", required=True)
ap.add_argument("--cycle", required=True)
ap.add_argument("--out", required=True)
args = ap.parse_args()
payload = build(args.gloss, args.cycle)
out = Path(args.out)
out.parent.mkdir(parents=True, exist_ok=True)
out.write_text(json.dumps(payload, indent=2) + "\n", encoding="utf-8")
print(f"wrote {out} (source={payload['source']}, frames={len(payload['frames'])})")
if __name__ == "__main__":
main()