BladeSzaSza's picture
fix: define REPO_NAME in hf_upload.sh (ensure_blade_space referenced it)
4948993 verified
Raw
History Blame Contribute Delete
1.96 kB
"""
Per-frame time series for the joints relevant to a screening test.
Builds angle-over-time series (used by the angle graph) and a per-joint flexion
summary at a chosen frame (degrees + open/closed label). Reuses the biomechanics
geometry helpers so angle definitions never diverge.
"""
from __future__ import annotations
import math
from formscout.agents.biomechanics import _angle_between_points, _get_joint
from formscout.analysis.relevant_joints import openness_label, relevant_angles
def angle_series(pose2d, test_name: str) -> dict[str, list[float]]:
"""Return {angle_name: [deg per frame]} for this test's relevant angles.
Frames where the angle cannot be measured hold NaN.
"""
angles = relevant_angles(test_name)
series: dict[str, list[float]] = {name: [] for name in angles}
for kps in pose2d.keypoints:
for name, (a, b, c) in angles.items():
pa, pb, pc = _get_joint(kps, a), _get_joint(kps, b), _get_joint(kps, c)
if pa and pb and pc:
series[name].append(_angle_between_points(pa, pb, pc))
else:
series[name].append(float("nan"))
return series
def relevant_flexion_at(pose2d, test_name: str, frame_idx: int) -> dict[str, dict]:
"""At one frame, the relevant joint angles with degree value + openness label.
Returns {angle_name: {"deg": float, "openness": str}}; angles that cannot be
measured at that frame are omitted.
"""
out: dict[str, dict] = {}
if not (0 <= frame_idx < len(pose2d.keypoints)):
return out
kps = pose2d.keypoints[frame_idx]
for name, (a, b, c) in relevant_angles(test_name).items():
pa, pb, pc = _get_joint(kps, a), _get_joint(kps, b), _get_joint(kps, c)
if pa and pb and pc:
deg = _angle_between_points(pa, pb, pc)
if not math.isnan(deg):
out[name] = {"deg": deg, "openness": openness_label(deg)}
return out