Developer Guide
This guide is for developers who want to contribute to or extend CTHarvester.
Architecture Overview
Module Structure
CTHarvester follows a modular architecture:
CTHarvester/
├── core/ # Core business logic
│ ├── progress_tracker.py # Progress tracking
│ ├── progress_manager.py # Progress management
│ ├── thumbnail_manager.py # Thumbnail coordination
│ ├── thumbnail_generator.py # Thumbnail generation logic
│ ├── thumbnail_worker.py # Worker threads
│ ├── sequential_processor.py # Sequential processing (Phase 4.1)
│ ├── volume_processor.py # Volume processing
│ └── worker_manager.py # Worker management
├── ui/ # User interface
│ ├── main_window.py # Main application window (789 lines)
│ ├── ctharvester_app.py # Custom QApplication subclass
│ ├── handlers/ # UI handler modules (Phase 4)
│ │ ├── thumbnail_creation_handler.py # Thumbnail generation (Phase 4.2)
│ │ ├── directory_open_handler.py # Directory opening (Phase 4.3)
│ │ ├── view_manager.py # 3D view management (Phase 4.4)
│ │ ├── export_handler.py # Export operations
│ │ ├── file_handler.py # File operations
│ │ └── settings_handler.py # Settings management
│ ├── dialogs/ # Dialog windows
│ │ ├── progress_dialog.py # Progress display
│ │ ├── info_dialog.py # Information dialogs
│ │ └── shortcut_dialog.py # Keyboard shortcuts
│ ├── widgets/ # Custom widgets
│ │ ├── mcube_widget.py # 3D marching cubes viewer
│ │ ├── object_viewer_2d.py # 2D image viewer
│ │ └── vertical_stack_slider.py # Range slider
│ └── setup/ # UI setup modules
│ └── main_window_setup.py # Window initialization
├── utils/ # Utility functions
│ ├── settings_manager.py # YAML settings
│ ├── common.py # Common utilities
│ ├── ui_utils.py # UI helper functions
│ ├── file_utils.py # File utilities
│ └── image_utils.py # Image processing utilities
├── config/ # Configuration
│ ├── constants.py # Application constants
│ ├── settings.yaml # Default settings
│ ├── shortcuts.py # Keyboard shortcuts
│ └── tooltips.py # Tooltip definitions
├── security/ # Security modules
│ └── file_validator.py # File validation & path traversal prevention
└── tests/ # Test suite (1,150 tests)
├── integration/ # Integration tests
├── property/ # Property-based tests
└── test_*.py # Unit tests
Design Principles
Separation of Concerns: UI, business logic, and data handling are separate
Modularity: Each module has a single, well-defined responsibility
Testability: Core logic is independent of UI for easy testing
Thread Safety: Proper synchronization for multithreaded operations
Security First: Input validation and secure file operations
Key Components
Progress Tracking:
SimpleProgressTracker
: Linear progress with ETAProgressManager
: Weighted multi-level progressSignal/slot connections for UI updates
Thumbnail Generation:
ThumbnailCreationHandler
: Orchestrates Rust/Python thumbnail generation (Phase 4.2)ThumbnailGenerator
: Core thumbnail generation logicThumbnailManager
: Coordinates worker threadsThumbnailWorker
: Processes individual thumbnailsSequentialProcessor
: Python fallback sequential processing (Phase 4.1)Support for both Rust (high-performance) and Python (fallback) implementations
UI Handlers (Phase 4 Refactoring):
ThumbnailCreationHandler
: Manages thumbnail generation workflowsDirectoryOpenHandler
: Handles directory selection and loadingViewManager
: Manages 3D view updates and synchronizationExportHandler
: Manages export operationsFileHandler
: File operations and validationSettingsHandler
: Window settings persistence
Settings Management:
YAML-based configuration
Platform-independent storage
Import/Export functionality
Dot notation access (
settings.get('app.language')
)
Security:
SecureFileValidator
: Path traversal preventionWhitelist-based file extension validation
Safe file operations
Development Setup
Prerequisites
Python 3.8+
Git
Virtual environment tool (venv or conda)
Optional: Rust toolchain for building native module
Setting Up Development Environment
Clone and setup:
git clone https://github.com/yourusername/CTHarvester.git cd CTHarvester # Create virtual environment python -m venv venv source venv/bin/activate # Linux/macOS # or venv\\Scripts\\activate # Windows # Install dependencies pip install -r requirements.txt pip install -r requirements-dev.txt # Development dependencies
Install pre-commit hooks:
pre-commit install
Run tests:
pytest tests/
Code Style and Standards
Python Style Guide
We follow PEP 8 with some modifications:
Line length: 100 characters (not 79)
Use double quotes for strings
Use type hints for function signatures
Use Google-style docstrings
Example:
def process_image(
image_path: str,
threshold: int = 128,
invert: bool = False
) -> np.ndarray:
"""Process a single CT image.
Args:
image_path: Path to the image file.
threshold: Grayscale threshold value (0-255).
invert: Whether to invert grayscale values.
Returns:
Processed image as numpy array.
Raises:
FileNotFoundError: If image_path doesn't exist.
ValueError: If threshold is out of range.
"""
# Implementation
pass
Docstring Style
Use Google-style docstrings for all public APIs:
def function_name(param1: type1, param2: type2) -> return_type:
"""Short one-line summary.
Longer description if needed. Can span multiple paragraphs.
Args:
param1: Description of param1.
param2: Description of param2.
Returns:
Description of return value.
Raises:
ExceptionType: When this exception is raised.
Example:
>>> result = function_name("foo", 42)
>>> print(result)
'expected output'
"""
Type Hints
Use type hints for all function signatures:
from typing import Optional, List, Dict, Tuple
def process_files(
files: List[str],
options: Optional[Dict[str, Any]] = None
) -> Tuple[int, int]:
"""Process multiple files."""
pass
Testing
Test Organization
Tests are organized by module:
tests/
├── test_progress_tracker.py
├── test_thumbnail_manager.py
├── test_settings_manager.py
└── test_file_validator.py
Running Tests
Run all tests:
pytest
Run specific test file:
pytest tests/test_settings_manager.py
Run with coverage:
pytest --cov=. --cov-report=html
Run specific test:
pytest tests/test_settings_manager.py::test_get_nested_setting
Writing Tests
Example test structure:
import pytest
from core.progress_tracker import SimpleProgressTracker, ProgressInfo
class TestSimpleProgressTracker:
"""Tests for SimpleProgressTracker class."""
def test_initialization(self):
"""Test tracker initialization."""
tracker = SimpleProgressTracker(total_items=100)
assert tracker.completed_items == 0
assert tracker.total_items == 100
def test_update_progress(self):
"""Test progress update."""
tracker = SimpleProgressTracker(total_items=100)
tracker.update(increment=10)
assert tracker.completed_items == 10
def test_eta_calculation(self):
"""Test ETA calculation after sufficient samples."""
results = []
def callback(info: ProgressInfo):
results.append(info)
tracker = SimpleProgressTracker(
total_items=100,
callback=callback
)
for i in range(10):
time.sleep(0.1)
tracker.update()
# After min_samples_for_eta, should have ETA
assert results[-1].eta_seconds is not None
@pytest.mark.parametrize("total,increment", [
(100, 1),
(1000, 10),
(50, 5),
])
def test_various_increments(self, total, increment):
"""Test with various total/increment combinations."""
tracker = SimpleProgressTracker(total_items=total)
for i in range(0, total, increment):
tracker.update(increment=increment)
assert tracker.completed_items == total
Test Coverage Goals
Overall coverage: >70%
Core modules: >80%
Security modules: >90%
Contributing
Contribution Workflow
Fork and Clone:
Fork the repository on GitHub
Clone your fork locally
Add upstream remote:
git remote add upstream https://github.com/original/CTHarvester.git
Create Feature Branch:
git checkout -b feature/your-feature-name
Make Changes:
Write code
Add tests
Update documentation
Run tests:
pytest
Check style:
flake8
orblack --check .
Commit:
git add . git commit -m "feat: Add your feature description"
Follow conventional commits format:
feat:
: New featurefix:
: Bug fixdocs:
: Documentation changesrefactor:
: Code refactoringtest:
: Adding testschore:
: Maintenance tasks
Push and Create PR:
git push origin feature/your-feature-name
Create pull request on GitHub
Fill out PR template
Link related issues
Wait for review
Code Review Process
All code changes go through review:
Automated Checks:
Tests must pass
Code coverage must not decrease
Style checks must pass
Manual Review:
At least one approving review required
Address review comments
Update as needed
Merge:
Squash and merge preferred
Delete branch after merge
Pull Request Guidelines
Good PR:
Focused on single feature/fix
Includes tests
Updates documentation
Clear description
Links to related issues
PR Template:
## Description
Brief description of changes
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Documentation update
- [ ] Refactoring
## Testing
- [ ] Tests added/updated
- [ ] All tests passing
- [ ] Manual testing performed
## Checklist
- [ ] Code follows style guidelines
- [ ] Self-review performed
- [ ] Documentation updated
- [ ] No new warnings
## Related Issues
Closes #123
Building and Packaging
Building Rust Module
cd rust_thumbnail
cargo build --release
cd ..
The compiled library will be placed in target/release/
.
Creating Executable
Using PyInstaller:
# Windows
pyinstaller --onefile --noconsole --icon=CTHarvester_64.png CTHarvester.py
# Linux/macOS
pyinstaller --onefile --icon=CTHarvester_64.png CTHarvester.py
Output:
Executable in
dist/
directoryStandalone, no Python required
Building Documentation
cd docs
make html
Output in docs/_build/html/
.
Release Process
Update Version:
Update
config/constants.py
Update
docs/conf.py
Update
setup.py
(if using)
Update Changelog:
Add release notes
List all changes since last release
Create Release:
git tag -a v0.3.0 -m "Release v0.3.0" git push origin v0.3.0
Build Artifacts:
Build executables for all platforms
Build documentation
Create source distribution
Publish Release:
Create GitHub release
Attach built artifacts
Copy changelog to release notes
Mark as latest release
Debugging Tips
Logging
CTHarvester uses Python’s logging module:
import logging
logger = logging.getLogger(__name__)
logger.debug("Detailed information")
logger.info("General information")
logger.warning("Warning message")
logger.error("Error occurred")
Set log level in settings or via command line.
Common Debugging Scenarios
Threading Issues:
Use
QMutexLocker
for thread-safe operationsCheck for race conditions with
threading.current_thread()
Use
logging
instead ofprint()
in threads
Memory Leaks:
Use
memory_profiler
to track memory usageCheck for circular references
Use weak references where appropriate
Performance Issues:
Profile with
cProfile
Use
line_profiler
for line-by-line profilingCheck I/O operations (often the bottleneck)
Qt/GUI Issues:
Only update UI from main thread
Use signals/slots for cross-thread communication
Check event loop is running
Resources
Documentation
Tools
pytest: Testing framework
black: Code formatter
flake8: Linter
mypy: Type checker
coverage.py: Coverage reporting
PyInstaller: Executable builder
Community
GitHub Issues: Bug reports and feature requests
Discussions: Questions and general discussion
Pull Requests: Code contributions
Wiki: Additional documentation
Getting Help
Check this documentation
Search existing issues
Ask in GitHub Discussions
Create new issue if needed
When asking for help, include:
Python version
Operating system
CTHarvester version
Error message (full traceback)
Minimal reproduction steps
What you’ve tried