Skip to content

Commit d22ac7f

Browse files
committed
Added install files and tests
1 parent 3be8227 commit d22ac7f

8 files changed

Lines changed: 482 additions & 31 deletions

File tree

.github/workflows/tests.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: Run Tests
2+
3+
on:
4+
push:
5+
branches: [ main, dev-v.1.1.0 ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
jobs:
10+
test:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- uses: actions/checkout@v3
15+
16+
- name: Set up Python
17+
uses: actions/setup-python@v4
18+
with:
19+
python-version: '3.10'
20+
21+
- name: Install dependencies
22+
run: |
23+
python -m pip install --upgrade pip
24+
pip install -r requirements.txt
25+
26+
- name: Run tests
27+
run: |
28+
python tests/run_tests.py

CHANGELOG.md

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,35 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8-
## [1.1.0] - 2025-11-15
8+
## [1.1.0] - 2025-11-16
99

1010
### Added
1111

12+
- **Automated Testing Infrastructure**: GitHub Actions CI/CD pipeline
13+
- Runs tests automatically on push to main and dev-v.1.1.0 branches
14+
- Executes on pull requests targeting main branch
15+
- Uses Python 3.10 on Ubuntu
16+
- Installs dependencies and runs test suite via `tests/run_tests.py`
17+
- Workflow configuration in `.github/workflows/tests.yml`
18+
19+
- **Test Suite**: Comprehensive unit tests for core functionality
20+
- Camera tests (`tests/test_camera.py`): 159 lines covering camera initialization, recording, frame buffering
21+
- Pose estimator tests (`tests/test_pose_estimator.py`): 105 lines for pose detection functionality
22+
- Pose renderer tests (`tests/test_pose_renderer.py`): 114 lines for wireframe rendering and angle calculations
23+
- Settings tests (`tests/test_settings.py`): 134 lines for settings persistence and retrieval
24+
- Test runner script (`tests/run_tests.py`) for easy execution
25+
- Test documentation in `tests/README.md`
26+
27+
- **Easy Installation Scripts**: Automated setup for all platforms
28+
- **macOS/Linux** (`install.sh`): Creates virtual environment, installs dependencies, creates application launcher
29+
- Detects Python version and validates compatibility (3.8-3.12)
30+
- Creates desktop shortcut or application bundle based on platform
31+
- Makes FrameLab easily accessible from Applications folder (macOS) or app menu (Linux)
32+
- **Windows** (`install.bat`): Equivalent functionality for Windows
33+
- Validates Python installation and version
34+
- Creates desktop shortcut for one-click launch
35+
- Provides helpful error messages for missing dependencies
36+
1237
- **Configurable Keyboard Shortcuts**: Full customization of all keyboard shortcuts
1338
- Access via File > Keyboard Shortcuts menu
1439
- Interactive key recording: click "Change" button and press desired key combination
@@ -107,6 +132,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
107132
- Global and per-camera side view mode preferences
108133
- Settings automatically applied when enabling pose estimation
109134

135+
### Changed
136+
137+
- **.gitignore Updates**: Enhanced to exclude local runtime data
138+
- Added `settings.json` to prevent personal settings from being committed
139+
- Added `db_athlete/` to exclude athlete data directories from version control
140+
- Keeps sensitive and user-specific data out of the repository
141+
110142
### Performance
111143

112144
- **FPS and Resolution Display**: New on-screen performance monitoring

README.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,57 @@ A professional multi-camera video analysis application for bike fitting and biom
5353

5454
### Installation
5555

56+
#### Option 1: Automated Installation (Recommended)
57+
58+
The easiest way to install FrameLab is using the provided installation scripts:
59+
60+
**macOS/Linux:**
61+
```bash
62+
git clone https://github.com/andrefecto/framelab.git
63+
cd framelab
64+
chmod +x install.sh
65+
./install.sh
66+
```
67+
68+
**Windows:**
69+
```cmd
70+
git clone https://github.com/andrefecto/framelab.git
71+
cd framelab
72+
install.bat
73+
```
74+
75+
**What the installation script does:**
76+
77+
1. **Python Version Check**: Verifies Python 3.8-3.12 is installed (3.13+ not yet supported due to MediaPipe compatibility)
78+
2. **Virtual Environment**: Creates an isolated Python environment in the `venv/` directory
79+
3. **Dependency Installation**: Installs all required packages from `requirements.txt`:
80+
- DearPyGUI (GPU-accelerated UI framework)
81+
- MediaPipe (AI pose estimation)
82+
- OpenCV (video processing)
83+
- NumPy (numerical computing)
84+
4. **Application Launcher**: Creates platform-specific shortcuts:
85+
- **macOS**: Creates `FrameLab.app` bundle in `~/Applications/` with icon
86+
- **Linux**: Creates `.desktop` entry in `~/.local/share/applications/`
87+
- **Windows**: Creates desktop shortcut with icon
88+
5. **Permissions**: Sets executable permissions on necessary files (macOS/Linux)
89+
90+
**After installation:**
91+
- **macOS**: Find FrameLab in your Applications folder or use Spotlight search (⌘+Space, type "FrameLab")
92+
- **Linux**: Find FrameLab in your application menu (Activities/Applications → FrameLab)
93+
- **Windows**: Double-click the FrameLab shortcut on your desktop or in Start Menu
94+
95+
**Troubleshooting Installation:**
96+
- **Python not found**: Install Python 3.8-3.12 from [python.org](https://www.python.org/downloads/)
97+
- Windows: Make sure to check "Add Python to PATH" during installation
98+
- macOS: Use Homebrew: `brew install python@3.12`
99+
- Linux: Use package manager: `sudo apt install python3 python3-pip python3-venv`
100+
- **Permission denied (macOS/Linux)**: Run `chmod +x install.sh` first
101+
- **Missing dependencies**: The script will show specific error messages if packages fail to install
102+
103+
#### Option 2: Manual Installation
104+
105+
If you prefer to install manually:
106+
56107
1. **Clone the repository**:
57108

58109
```bash

camera/camera.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ def initialize(self, max_display_width, max_display_height):
163163
logger.debug(f" Path: {self.video_path}")
164164
return True
165165

166+
source_type = "Video file" if self.is_video_file else "Camera"
166167
logger.error(f"Failed to read test frame from {source_type} {self.camera_id}")
167168
return False
168169

gui/layout.py

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -815,39 +815,38 @@ def is_mouse_over_virtual_divider(mouse_x, mouse_y, divider_type):
815815
# Increased detection width for easier clicking
816816
DETECT_WIDTH = 30 # 30 pixels on each side for easier clicking
817817

818+
# Calculate divider position based on window size and state, not quadrant positions
819+
# This ensures it's always accurate even if window was just resized
820+
window_width = dpg.get_item_width("main_window")
821+
window_height = dpg.get_item_height("main_window")
822+
823+
# Calculate available space (matching update_quadrant_sizes logic)
824+
available_width = max(window_width - 20, 640)
825+
available_height = max(window_height - 60, 400)
826+
818827
if divider_type == "vertical":
819-
# For vertical divider, use quadrant configuration
828+
# Get Q0 position to calculate absolute divider position
820829
if dpg.does_item_exist("position_group_0"):
821830
try:
822-
# Get the state which contains configuration info
823-
state_0 = dpg.get_item_state("position_group_0")
824-
if "rect_size" in state_0:
825-
q0_width = state_0["rect_size"][0]
826-
q0_pos = dpg.get_item_pos("position_group_0")
827-
# Divider is at the right edge of Q0
828-
divider_x = q0_pos[0] + q0_width
829-
830-
window_height = dpg.get_item_height("main_window")
831-
return (divider_x - DETECT_WIDTH <= mouse_x <= divider_x + DETECT_WIDTH and
832-
0 <= mouse_y <= window_height)
831+
q0_pos = dpg.get_item_pos("position_group_0")
832+
# Calculate divider X from state and available width
833+
divider_x = q0_pos[0] + int(available_width * state.vertical_divider_position)
834+
835+
return (divider_x - DETECT_WIDTH <= mouse_x <= divider_x + DETECT_WIDTH and
836+
0 <= mouse_y <= window_height)
833837
except:
834838
pass
835839

836840
elif divider_type == "horizontal":
837-
# For horizontal divider, use quadrant configuration (mirror of vertical)
841+
# Get Q0 position to calculate absolute divider position
838842
if dpg.does_item_exist("position_group_0"):
839843
try:
840-
# Get the state which contains configuration info
841-
state_0 = dpg.get_item_state("position_group_0")
842-
if "rect_size" in state_0:
843-
q0_height = state_0["rect_size"][1]
844-
q0_pos = dpg.get_item_pos("position_group_0")
845-
# Divider is at the bottom edge of Q0
846-
divider_y = q0_pos[1] + q0_height
847-
848-
window_width = dpg.get_item_width("main_window")
849-
return (0 <= mouse_x <= window_width and
850-
divider_y - DETECT_WIDTH <= mouse_y <= divider_y + DETECT_WIDTH)
844+
q0_pos = dpg.get_item_pos("position_group_0")
845+
# Calculate divider Y from state and available height
846+
divider_y = q0_pos[1] + int(available_height * state.horizontal_divider_position)
847+
848+
return (0 <= mouse_x <= window_width and
849+
divider_y - DETECT_WIDTH <= mouse_y <= divider_y + DETECT_WIDTH)
851850
except:
852851
pass
853852

install.bat

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
@echo off
2+
REM FrameLab Installation Script for Windows
3+
REM This script sets up FrameLab and creates a desktop shortcut
4+
5+
echo ======================================
6+
echo FrameLab Installation Script
7+
echo ======================================
8+
echo.
9+
10+
REM Get the directory where this script is located
11+
set "SCRIPT_DIR=%~dp0"
12+
cd /d "%SCRIPT_DIR%"
13+
14+
REM Check for Python 3
15+
python --version >nul 2>&1
16+
if errorlevel 1 (
17+
echo Error: Python 3 is not installed.
18+
echo Please install Python 3.8 to 3.12 from https://www.python.org/downloads/
19+
echo Make sure to check "Add Python to PATH" during installation.
20+
pause
21+
exit /b 1
22+
)
23+
24+
REM Get Python version
25+
for /f "tokens=2" %%i in ('python --version 2^>^&1') do set PYTHON_VERSION=%%i
26+
echo Found Python version: %PYTHON_VERSION%
27+
28+
REM Extract major and minor version numbers
29+
for /f "tokens=1,2 delims=." %%a in ("%PYTHON_VERSION%") do (
30+
set PYTHON_MAJOR=%%a
31+
set PYTHON_MINOR=%%b
32+
)
33+
34+
REM Check if Python version is compatible (3.8 to 3.12)
35+
if not "%PYTHON_MAJOR%"=="3" (
36+
echo Error: Python 3 is required ^(found Python %PYTHON_MAJOR%^)
37+
pause
38+
exit /b 1
39+
)
40+
41+
if %PYTHON_MINOR% LSS 8 (
42+
echo Error: Python 3.8 or higher is required ^(found Python %PYTHON_VERSION%^)
43+
echo Please install Python 3.8 to 3.12 from https://www.python.org/downloads/
44+
pause
45+
exit /b 1
46+
)
47+
48+
if %PYTHON_MINOR% GTR 12 (
49+
echo Warning: Python 3.12 or lower is recommended ^(found Python %PYTHON_VERSION%^)
50+
echo Python 3.13+ may have compatibility issues.
51+
set /p CONTINUE="Continue anyway? (y/n): "
52+
if /i not "%CONTINUE%"=="y" (
53+
exit /b 1
54+
)
55+
)
56+
57+
echo [OK] Python version compatible
58+
echo.
59+
60+
REM Create virtual environment if it doesn't exist
61+
if not exist "venv" (
62+
echo Creating virtual environment...
63+
python -m venv venv
64+
echo [OK] Virtual environment created
65+
) else (
66+
echo [OK] Virtual environment already exists
67+
)
68+
echo.
69+
70+
REM Activate virtual environment
71+
echo Activating virtual environment...
72+
call venv\Scripts\activate.bat
73+
74+
REM Upgrade pip
75+
echo Upgrading pip...
76+
python -m pip install --upgrade pip --quiet
77+
78+
REM Install dependencies
79+
echo Installing dependencies...
80+
if exist "requirements.txt" (
81+
pip install -r requirements.txt --quiet
82+
echo [OK] Dependencies installed
83+
) else (
84+
echo Error: requirements.txt not found
85+
pause
86+
exit /b 1
87+
)
88+
echo.
89+
90+
REM Create launcher script
91+
echo Creating launcher script...
92+
(
93+
echo @echo off
94+
echo REM FrameLab Launcher Script
95+
echo cd /d "%SCRIPT_DIR%"
96+
echo call venv\Scripts\activate.bat
97+
echo python main.py
98+
echo pause
99+
) > run_framelab.bat
100+
101+
echo [OK] Launcher script created
102+
echo.
103+
104+
REM Create desktop shortcut
105+
echo Creating desktop shortcut...
106+
107+
REM Create VBScript to create shortcut
108+
(
109+
echo Set oWS = WScript.CreateObject^("WScript.Shell"^)
110+
echo sDesktop = oWS.SpecialFolders^("Desktop"^)
111+
echo Set oLink = oWS.CreateShortcut^(sDesktop ^& "\FrameLab.lnk"^)
112+
echo oLink.TargetPath = "%SCRIPT_DIR%run_framelab.bat"
113+
echo oLink.WorkingDirectory = "%SCRIPT_DIR%"
114+
echo oLink.Description = "FrameLab - Multi-camera video analysis"
115+
echo oLink.Save
116+
) > create_shortcut.vbs
117+
118+
cscript //nologo create_shortcut.vbs
119+
del create_shortcut.vbs
120+
121+
echo [OK] Desktop shortcut created
122+
echo.
123+
124+
echo ======================================
125+
echo Installation Complete!
126+
echo ======================================
127+
echo.
128+
echo You can now:
129+
echo 1. Double-click the "FrameLab" shortcut on your desktop
130+
echo 2. Or run: run_framelab.bat
131+
echo.
132+
echo To run manually:
133+
echo venv\Scripts\activate.bat
134+
echo python main.py
135+
echo.
136+
pause

0 commit comments

Comments
 (0)