Thank you for your interest in contributing to SlicerRoboTMS! We welcome contributions from researchers, developers, and medical professionals. This document outlines our contribution process and guidelines.
We are committed to providing a welcoming and inclusive environment for all contributors.
- Python 3.8 or higher
- 3D Slicer 5.8.1 or later
- ROS 1 Noetic (for robotic experiments)
- Git and basic command-line familiarity
# Clone the repository
git clone https://github.com/OpenRoboTMS/SlicerRoboTMS.git
cd SlicerRoboTMS
# Initialize submodules
git submodule update --init --recursive
# Install development dependencies
pip install flake8 pylint pre-commit
# Set up pre-commit hooks
pre-commit installFound a bug? Please open an issue on GitHub with:
- Clear, descriptive title
- Detailed description of the problem
- Steps to reproduce
- Expected vs. actual behavior
- Environment details (OS, Slicer version, ROS version)
- Relevant logs (see
logs/directory)
Have an idea for improvement? Open an issue with:
- Clear description of the feature
- Use case and motivation
- Proposed implementation (if applicable)
- Any relevant references or papers
Help improve our documentation:
- Typo fixes
- Clarifications
- New examples or tutorials
- Better diagrams or visualizations
Submit bug fixes, optimizations, or new features:
We follow the 3D Slicer Python Style Guide to stay consistent with the Slicer community.
Naming Conventions:
- Methods and variables:
camelCase(e.g.,setupROSConnection,updateFromROS) - Classes:
PascalCase(e.g.,CalibrationLogic,URDFParser) - Constants:
UPPER_CASE_WITH_UNDERSCORES(e.g.,IGTL_CONFIG,UPDATE_RATES) - Private methods: prefix with underscore + camelCase (
_createLink,_getRASToMri)
Formatting:
- Maximum line length: 120 characters
- Indentation: 4 spaces
- Use type hints for function parameters and returns
- Docstring format: Google style (Args, Returns, Raises sections)
Example Method:
def loadModelFile(self, filename: str, nodeName: str, visible: bool = True) -> None:
"""Load a STL model file into the Slicer scene.
Args:
filename: STL filename (relative to models directory).
nodeName: Name to assign to the created model node.
visible: Initial visibility of the model. Default: True
Raises:
None - logs warnings/errors internally if file is not found.
"""
filepath = os.path.join(self.modelsPath, filename)
if not os.path.exists(filepath):
logging.warning(f"Model file not found: {filepath}")
return
# ...Docstring Sections (required for public methods):
- Summary (one-liner)
- Extended description (if needed)
- Args: parameter type and description
- Returns: return type and description
- Raises: exceptions that may be raised
Code Quality Standards:
- Linting: must pass
flake8with no errors - Target: pass
pylintwith score > 8.0 - Type checking: compatible with
mypy - Testing: all new code must include unit tests
Before committing, the following checks run automatically:
- Flake8 linting
- Pylint analysis
- Trailing whitespace removal
- File ending normalization
To run checks manually:
flake8 SlicerRoboTMS/
pylint SlicerRoboTMS/Calibration SlicerRoboTMS/Navigation SlicerRoboTMS/Registration SlicerRoboTMS/utils/-
Create a fork of the repository on GitHub
-
Create a feature branch from
main:git checkout -b feature/your-feature-name
-
Make your changes with clear, descriptive commits:
git commit -m "Add feature: brief description of changes" -
Push to your fork:
git push origin feature/your-feature-name
-
Open a Pull Request to the main repository with:
- Clear title describing the change
- Detailed description of what was changed and why
- Reference to any related issues (e.g., "Fixes #123")
- Test results showing passing tests
- Screenshots for UI changes
-
Code Review: Address feedback from reviewers
- Push updates to the same branch
- Request re-review when ready
-
Merge: Once approved, maintainers will merge your PR
All contributions must include appropriate tests. We use Python's unittest framework.
Test Location: SlicerRoboTMS/<Module>/Testing/Python/
Test Template:
import unittest
import numpy as np
from YourModule import YourClass
class TestYourFeature(unittest.TestCase):
"""Test cases for YourFeature."""
def setUp(self):
"""Set up test fixtures."""
self.instance = YourClass()
def tearDown(self):
"""Clean up after tests."""
pass
def test_normal_case(self):
"""Test normal/expected behavior."""
result = self.instance.method(valid_input)
self.assertEqual(result, expected_output)
def test_edge_case(self):
"""Test boundary conditions."""
# Test with empty input, extreme values, etc.
pass
def test_error_handling(self):
"""Test error cases are handled correctly."""
with self.assertRaises(ValueError):
self.instance.method(invalid_input)
if __name__ == '__main__':
unittest.main()Run All Tests:
python -m pytest SlicerRoboTMS/*/Testing/Python/ -vWhen adding new features:
- Write docstrings in Google format
- Update relevant README files
- Add example code if applicable
Write clear, descriptive commit messages:
Short summary (50 chars or less)
More detailed explanation of what changed and why (wrap at 72 chars).
Reference relevant issues: Fixes #123
- Bullet points for multiple changes
- Explain the what and why, not the how
All pull requests undergo:
- Automated checks: Linting, tests
- Code review: At least one maintainer reviews for:
- Code quality and style
- Test coverage
- Documentation completeness
- Consistency with project standards
- Approval: Two approvals required for merge
- Issues: Search existing GitHub Issues
- Discussions: Check GitHub Discussions
Contributors will be recognized in:
- Project README
- Release notes
- GitHub contributors page
Thank you for making SlicerRoboTMS better!