Spaces:
Running on Zero
Running on Zero
| from __future__ import annotations | |
| from pathlib import Path | |
| import math | |
| import sys | |
| from typing import Callable | |
| import unittest | |
| sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src")) | |
| from pozify.contracts import ( | |
| PoseFrame, | |
| PoseSequence, | |
| Rep, | |
| Reps, | |
| UserProfile, | |
| VideoManifest, | |
| ) | |
| from pozify.exercises import create_exercise_strategy | |
| def _frame(frame_index: int, landmarks: dict[str, dict[str, float]]) -> PoseFrame: | |
| return PoseFrame( | |
| frame_index=frame_index, | |
| timestamp_sec=round(frame_index / 30.0, 3), | |
| landmarks=landmarks, | |
| world_landmarks={}, | |
| pose_quality={"mean_visibility": 0.95, "normalized": True}, | |
| ) | |
| def _wave(frame_index: int, cycle_frames: int) -> float: | |
| return (1.0 - math.cos(2.0 * math.pi * (frame_index / cycle_frames))) / 2.0 | |
| def _push_up_landmarks(depth: float, *, hand_ratio: float = 1.7) -> dict[str, dict[str, float]]: | |
| shoulder_y = 0.38 + depth * 0.16 | |
| hip_y = 0.46 + depth * 0.16 | |
| ankle_y = 0.54 + depth * 0.16 | |
| elbow_y = 0.46 + depth * 0.1 | |
| wrist_y = 0.5 + depth * 0.04 | |
| shoulder_width = 0.4 | |
| hand_width = shoulder_width * hand_ratio | |
| return { | |
| "left_shoulder": {"x": 0.3, "y": shoulder_y}, | |
| "right_shoulder": {"x": 0.7, "y": shoulder_y}, | |
| "left_elbow": {"x": 0.36 + depth * 0.02, "y": elbow_y}, | |
| "right_elbow": {"x": 0.64 - depth * 0.02, "y": elbow_y}, | |
| "left_wrist": {"x": 0.5 - hand_width / 2, "y": wrist_y}, | |
| "right_wrist": {"x": 0.5 + hand_width / 2, "y": wrist_y}, | |
| "left_hip": {"x": 0.42, "y": hip_y}, | |
| "right_hip": {"x": 0.58, "y": hip_y}, | |
| "left_ankle": {"x": 0.44, "y": ankle_y}, | |
| "right_ankle": {"x": 0.56, "y": ankle_y}, | |
| } | |
| def _knee_push_up_landmarks(depth: float, *, hand_ratio: float = 1.1) -> dict[str, dict[str, float]]: | |
| shoulder_y = 0.38 + depth * 0.16 | |
| hip_y = 0.46 + depth * 0.16 | |
| knee_y = hip_y + 0.03 | |
| ankle_y = hip_y + 0.28 | |
| elbow_y = 0.46 + depth * 0.1 | |
| wrist_y = 0.5 + depth * 0.04 | |
| shoulder_width = 0.4 | |
| hand_width = shoulder_width * hand_ratio | |
| return { | |
| "left_shoulder": {"x": 0.3, "y": shoulder_y}, | |
| "right_shoulder": {"x": 0.7, "y": shoulder_y}, | |
| "left_elbow": {"x": 0.36 + depth * 0.02, "y": elbow_y}, | |
| "right_elbow": {"x": 0.64 - depth * 0.02, "y": elbow_y}, | |
| "left_wrist": {"x": 0.5 - hand_width / 2, "y": wrist_y}, | |
| "right_wrist": {"x": 0.5 + hand_width / 2, "y": wrist_y}, | |
| "left_hip": {"x": 0.42, "y": hip_y}, | |
| "right_hip": {"x": 0.58, "y": hip_y}, | |
| "left_knee": {"x": 0.44, "y": knee_y}, | |
| "right_knee": {"x": 0.56, "y": knee_y}, | |
| "left_ankle": {"x": 0.44, "y": ankle_y}, | |
| "right_ankle": {"x": 0.56, "y": ankle_y}, | |
| } | |
| def _straight_leg_push_up_landmarks(depth: float) -> dict[str, dict[str, float]]: | |
| shoulder_y = 0.38 + depth * 0.1 | |
| hip_y = 0.46 + depth * 0.1 | |
| knee_y = 0.5 + depth * 0.1 | |
| ankle_y = 0.52 + depth * 0.1 | |
| elbow_y = 0.46 + depth * 0.06 | |
| wrist_y = 0.52 + depth * 0.02 | |
| return { | |
| "left_shoulder": {"x": 0.3, "y": shoulder_y}, | |
| "right_shoulder": {"x": 0.32, "y": shoulder_y}, | |
| "left_elbow": {"x": 0.35, "y": elbow_y}, | |
| "right_elbow": {"x": 0.37, "y": elbow_y}, | |
| "left_wrist": {"x": 0.42, "y": wrist_y}, | |
| "right_wrist": {"x": 0.44, "y": wrist_y}, | |
| "left_hip": {"x": 0.58, "y": hip_y}, | |
| "right_hip": {"x": 0.6, "y": hip_y}, | |
| "left_knee": {"x": 0.72, "y": knee_y}, | |
| "right_knee": {"x": 0.74, "y": knee_y}, | |
| "left_ankle": {"x": 0.88, "y": ankle_y}, | |
| "right_ankle": {"x": 0.9, "y": ankle_y}, | |
| } | |
| def _squat_landmarks(depth: float, *, stance_ratio: float = 1.5) -> dict[str, dict[str, float]]: | |
| shoulder_width = 0.2 | |
| stance_width = shoulder_width * stance_ratio | |
| hip_y = 0.52 + depth * 0.22 | |
| shoulder_y = 0.28 + depth * 0.06 | |
| knee_y = 0.7 | |
| return { | |
| "left_shoulder": {"x": 0.4, "y": shoulder_y}, | |
| "right_shoulder": {"x": 0.6, "y": shoulder_y}, | |
| "left_hip": {"x": 0.43, "y": hip_y}, | |
| "right_hip": {"x": 0.57, "y": hip_y}, | |
| "left_knee": {"x": 0.43 + depth * 0.05, "y": knee_y}, | |
| "right_knee": {"x": 0.57 - depth * 0.05, "y": knee_y}, | |
| "left_ankle": {"x": 0.5 - stance_width / 2, "y": 0.92}, | |
| "right_ankle": {"x": 0.5 + stance_width / 2, "y": 0.92}, | |
| } | |
| def _shoulder_press_landmarks(lift: float, *, partial: bool = True) -> dict[str, dict[str, float]]: | |
| wrist_top = 0.56 if partial else 0.42 | |
| wrist_y = 0.76 - lift * (0.76 - wrist_top) | |
| elbow_y = 0.6 - lift * 0.06 | |
| return { | |
| "left_shoulder": {"x": 0.42, "y": 0.42}, | |
| "right_shoulder": {"x": 0.58, "y": 0.42}, | |
| "left_elbow": {"x": 0.4 - lift * 0.02, "y": elbow_y}, | |
| "right_elbow": {"x": 0.6 + lift * 0.02, "y": elbow_y}, | |
| "left_wrist": {"x": 0.4, "y": wrist_y}, | |
| "right_wrist": {"x": 0.6, "y": wrist_y}, | |
| "left_hip": {"x": 0.44, "y": 0.74}, | |
| "right_hip": {"x": 0.56, "y": 0.74}, | |
| } | |
| def _sequence(exercise: str) -> PoseSequence: | |
| frames = [] | |
| for frame_index in range(25): | |
| wave = _wave(frame_index, 24) | |
| if exercise == "push_up": | |
| landmarks = _push_up_landmarks(wave) | |
| elif exercise == "shoulder_press": | |
| landmarks = _shoulder_press_landmarks(wave) | |
| else: | |
| landmarks = _squat_landmarks(wave) | |
| frames.append(_frame(frame_index, landmarks)) | |
| return PoseSequence( | |
| frames=frames, | |
| normalized=True, | |
| smoothing_method="none", | |
| pose_valid_ratio=1.0, | |
| ) | |
| def _custom_sequence( | |
| landmark_factory: Callable[[float], dict[str, dict[str, float]]], | |
| ) -> PoseSequence: | |
| frames = [] | |
| for frame_index in range(25): | |
| frames.append(_frame(frame_index, landmark_factory(_wave(frame_index, 24)))) | |
| return PoseSequence( | |
| frames=frames, | |
| normalized=True, | |
| smoothing_method="none", | |
| pose_valid_ratio=1.0, | |
| ) | |
| def _reps(exercise: str) -> Reps: | |
| return Reps( | |
| exercise=exercise, | |
| reps=[Rep(1, 0, 12, 24, 0.0, 0.4, 0.8)], | |
| partial_reps=[], | |
| ) | |
| def _profile() -> UserProfile: | |
| return UserProfile( | |
| goal="beginner_practice", | |
| experience_level="beginner", | |
| intended_exercise="auto", | |
| intended_variation=None, | |
| known_limitations=[], | |
| equipment="bodyweight", | |
| ) | |
| def _video_manifest(sequence: PoseSequence) -> VideoManifest: | |
| return VideoManifest( | |
| video_path=None, | |
| fps=30.0, | |
| duration_sec=round(len(sequence.frames) / 30.0, 3), | |
| total_frames=len(sequence.frames), | |
| sampled_frames=len(sequence.frames), | |
| width=720, | |
| height=1280, | |
| codec=None, | |
| container=None, | |
| brightness_mean=None, | |
| blur_laplacian_var=None, | |
| quality_warnings=[], | |
| analysis_allowed=True, | |
| ) | |
| def _exercise_strategy(exercise: str, sequence: PoseSequence, profile: UserProfile | None = None): | |
| return create_exercise_strategy( | |
| exercise, | |
| video_manifest=_video_manifest(sequence), | |
| pose_sequence=sequence, | |
| profile=profile or _profile(), | |
| ) | |
| class RepAnalysisVariationTests(unittest.TestCase): | |
| def test_push_up_metrics_detect_wide_grip_variation(self) -> None: | |
| sequence = _sequence("push_up") | |
| exercise = _exercise_strategy("push_up", sequence) | |
| analysis = exercise.analyze_reps(_reps("push_up")) | |
| variation = exercise.resolve_variation(analysis) | |
| self.assertEqual(variation.detected_variation, "wide_grip_push_up") | |
| self.assertIn("wide_hand_placement", variation.not_issues) | |
| self.assertGreater(analysis.items[0].metrics["hand_width_ratio"], 1.45) | |
| self.assertIn("body_line_score", analysis.items[0].metrics) | |
| def test_push_up_metrics_detect_knee_push_up_variation(self) -> None: | |
| sequence = _custom_sequence(_knee_push_up_landmarks) | |
| exercise = _exercise_strategy("push_up", sequence) | |
| analysis = exercise.analyze_reps(_reps("push_up")) | |
| variation = exercise.resolve_variation(analysis) | |
| self.assertEqual(variation.detected_variation, "knee_push_up") | |
| self.assertIn("knee_contact", variation.not_issues) | |
| self.assertGreaterEqual(analysis.aggregate_metrics["avg_knee_support_score"], 0.8) | |
| def test_straight_leg_push_up_does_not_false_positive_as_knee_push_up(self) -> None: | |
| sequence = _custom_sequence(_straight_leg_push_up_landmarks) | |
| exercise = _exercise_strategy("push_up", sequence) | |
| analysis = exercise.analyze_reps(_reps("push_up")) | |
| variation = exercise.resolve_variation(analysis) | |
| self.assertNotEqual(variation.detected_variation, "knee_push_up") | |
| self.assertNotIn("knee_contact", variation.not_issues) | |
| self.assertLess(analysis.aggregate_metrics["avg_knee_support_score"], 0.8) | |
| def test_squat_metrics_detect_wide_stance_variation(self) -> None: | |
| sequence = _sequence("squat") | |
| exercise = _exercise_strategy("squat", sequence) | |
| analysis = exercise.analyze_reps(_reps("squat")) | |
| variation = exercise.resolve_variation(analysis) | |
| self.assertEqual(variation.detected_variation, "wide_squat_stance") | |
| self.assertIn("wide_stance", variation.not_issues) | |
| self.assertGreater(analysis.items[0].metrics["stance_width_ratio"], 1.35) | |
| self.assertIn("min_knee_angle_deg", analysis.items[0].metrics) | |
| def test_shoulder_press_metrics_detect_partial_press_variation(self) -> None: | |
| sequence = _sequence("shoulder_press") | |
| exercise = _exercise_strategy("shoulder_press", sequence) | |
| analysis = exercise.analyze_reps(_reps("shoulder_press")) | |
| variation = exercise.resolve_variation(analysis) | |
| self.assertEqual(variation.detected_variation, "partial_press") | |
| self.assertIn("partial_range_of_motion", variation.not_issues) | |
| self.assertIn("lockout_quality", analysis.items[0].metrics) | |
| self.assertLess(analysis.aggregate_metrics["avg_wrist_travel"], 0.24) | |
| def test_profile_intended_variation_overrides_metric_rule(self) -> None: | |
| profile = UserProfile( | |
| goal="beginner_practice", | |
| experience_level="beginner", | |
| intended_exercise="push_up", | |
| intended_variation="close_grip_push_up", | |
| known_limitations=[], | |
| equipment="bodyweight", | |
| ) | |
| sequence = _sequence("push_up") | |
| exercise = _exercise_strategy("push_up", sequence, profile) | |
| analysis = exercise.analyze_reps(_reps("push_up")) | |
| variation = exercise.resolve_variation(analysis) | |
| self.assertEqual(variation.detected_variation, "close_grip_push_up") | |
| self.assertEqual(variation.variation_confidence, 0.95) | |
| self.assertIn("close_hand_placement", variation.not_issues) | |
| if __name__ == "__main__": | |
| unittest.main() | |