Contributing to DBS Annotator
We welcome contributions to DBS Annotator! This page is the authoritative
contributor guide for the repository. The short CONTRIBUTING.md at the
repository root is a pointer into this page.
Getting Started
Prerequisites
To contribute to this project, you should have:
Python 3.12 or newer (matches
requires-pythoninpyproject.toml; CI uses 3.12 on Ubuntu, Windows, and macOS).uv (https://github.com/astral-sh/uv) for dependency management and running tools.
Git installed and configured.
Familiarity with PySide6 / Qt is helpful but not required. The codebase follows a Model-View-Controller (MVC) structure under
src/dbs_annotator/.Understanding of deep brain stimulation concepts is helpful for clinical contributions but not required for code or documentation work.
Development Setup
Fork the repository on GitHub and clone your fork:
git clone https://github.com/<your-username>/DBSAnnotator.git cd DBSAnnotator
Create the virtual environment and install all dev dependencies (
uvreadspyproject.tomlanduv.lock; no manualvenvactivation is needed):uv sync --locked --dev
To additionally install the Briefcase packaging tools, use the
buildgroup:uv sync --locked --dev --group build
To build the documentation locally, use the
docsgroup:uv sync --locked --group docs --no-dev
Install the git pre-commit hooks (ruff, ty, actionlint,
uv lockcheck):uv run pre-commit install
Run the application to verify the installation:
uv run python -m dbs_annotator # or, once installed, the console script declared in pyproject.toml uv run dbs-annotator
Types of Contributions
We welcome the following types of contributions:
Bug Reports
If you find a bug, please:
Check existing issues to see if it’s already reported.
Create a new issue with:
Clear title describing the bug.
Steps to reproduce the issue.
Expected vs actual behaviour.
System information (OS, Python version, application version from
dbs_annotator.__version__).Screenshots or a short screen recording if the issue is in the GUI.
Feature Requests
For new features:
Check existing issues for similar requests.
Open an issue describing:
The feature you’d like to see.
Why it would be useful (clinical motivation, research workflow, etc.).
How you envision it working.
Any implementation ideas you have.
Code Contributions
We accept code contributions through pull requests. Please follow these guidelines:
Create a feature branch off
main(or the currently active integration branch):git checkout -b feature/your-feature-name
Make your changes following the coding standards below.
Run the local quality gate before pushing:
uv run ruff format . uv run ruff check . uv run ty check . uv run pytest
Commit your changes using a short, descriptive message (Conventional Commits are encouraged but not required):
git commit -m "feat: add directional-lead contact picker"
Push to your fork and open a pull request against the upstream repository.
Documentation Improvements
Documentation lives in this docs/ tree (Sphinx + reStructuredText) plus
README.md and CHANGELOG.md at the repository root. We welcome:
New or revised user-workflow pages.
API docstring improvements (Google or NumPy style; rendered by
sphinx.ext.napoleon).Additional examples, screenshots, or short screencasts.
Fixing typos and grammatical errors.
Build the docs locally before submitting:
uv sync --locked --group docs --no-dev
uv run sphinx-build -b html -W --keep-going docs docs/_build/html
uv run sphinx-build -b linkcheck docs docs/_build/linkcheck
Optional: regenerate UI screenshot artifacts for docs (uploaded as CI artifact):
DOCS_SCREENSHOT_DIR=docs/_static \
uv run pytest tests/docs/test_docs_screenshots.py -m docs_screenshot -q
On Windows, do **not** set ``QT_QPA_PLATFORM=offscreen`` (text renders as
empty boxes). The test harness selects the native platform automatically.
Sphinx-related paths under docs/:
``docs/_static/`` — Keep in version control. These are source assets (images, optional extra CSS/JS). Sphinx only copies them into
docs/_build/html/_static/when you build; the underscore is a Sphinx convention for “static inputs”, not garbage output.``docs/_templates/`` (including
_templates/autosummary/if present) — Keep in version control when the.html/.rstfiles there are hand-written Jinja templates that customize the HTML builder or autosummary. They are part of your documentation source, not generated API stubs.``docs/_autosummary/`` at the project root (next to your
.rstsources) — Do not commit. Those files are generated stubs produced bysphinx.ext.autosummary; they belong in.gitignoreand are recreated bysphinx-build(or your docs CI job).``docs/_generated/`` — Depends on your workflow. If that directory holds output from a script (for example includes generated from Python constants), you can either (a) commit the files so a plain
sphinx-buildworks everywhere, with CI checking they are up to date, or (b) gitignore them and always run the generator before Sphinx in CI and locally. Do not delete the folder if you still.. include::it from an.rstfile unless you switch fully to (b) and teach CI to regenerate it.
Never commit the HTML tree docs/_build/ (already ignored).
Code Standards
Style Guidelines
Formatting and linting are enforced by ruff (see [tool.ruff] in
pyproject.toml) and static typing is checked by ty. Both run in CI and
as pre-commit hooks, so local runs should stay green.
Formatter:
ruff format(line length 88).Linter:
ruff checkwith rulesE, W, F, I, N, UP, B, C4.Type checker:
ty check ..Docstrings: Google or NumPy style (Napoleon is enabled).
Naming:
snake_casefor functions and variables;PascalCasefor classes; module-private names prefixed with a single underscore.
Example:
def calculate_total_amplitude(
contact_states: dict[int, ContactState],
contact_amplitudes: dict[int, float],
) -> float:
"""Sum the cathodic amplitude contributed by each active contact.
Args:
contact_states: Mapping from contact index to its active state.
contact_amplitudes: Mapping from contact index to amplitude in mA.
Returns:
Total delivered cathodic amplitude in milliamps.
Raises:
ValueError: If ``contact_states`` is empty.
"""
if not contact_states:
raise ValueError("Contact states cannot be empty")
total = 0.0
for contact_idx, state in contact_states.items():
if state is ContactState.CATHODIC:
total += contact_amplitudes.get(contact_idx, 0.0)
return total
Testing
All new features should include tests. The project uses pytest with
pytest-qt for GUI interaction tests.
Unit tests for models, utilities, and pure-logic controllers.
GUI tests using
pytest-qt(qtbotfixture) for widget behaviour.Integration tests marked with
@pytest.mark.integrationfor cross-module behaviour.Slow flows may be marked
@pytest.mark.slowand skipped locally withpytest -m "not slow".
Example:
import pytest
from dbs_annotator.models.electrode_viewer import ElectrodeCanvas
@pytest.mark.gui
def test_electrode_canvas_scales_to_widget(qtbot):
canvas = ElectrodeCanvas()
qtbot.addWidget(canvas)
canvas.resize(400, 600)
assert canvas.calculate_scale() > 0
Run tests with:
uv run pytest
On headless Linux (including CI) set QT_QPA_PLATFORM=offscreen so Qt does
not require a display server:
QT_QPA_PLATFORM=offscreen uv run pytest
GUI Testing
For Qt components:
Test widget construction using the
qtbotfixture.Test user interactions (clicks, key presses, text input).
Test data flow between views, controllers, and models.
Test error handling paths surfaced through the UI.
Pull Request Process
Before Submitting
Update documentation in
docs/when user-visible behaviour changes.Add a Towncrier fragment under
newsfragments/. Types follow Types of changes in Keep a Changelog (added,changed,deprecated,removed,fixed,security); for examplenewsfragments/<PR>.changed.mdfor a doc-only update.CHANGELOG.mdis assembled from fragments at release time.Add or update tests for new functionality.
Run the local quality gate:
ruff format,ruff check,ty check,pytest.Regenerate the lockfile if you changed dependencies in
pyproject.toml(including thebuildgroup used by Briefcase) and commit the updateduv.lock:uv lock
Pull Request Template
When creating a pull request, please include:
Description
Brief description of the change.
Motivation (clinical workflow, bug, refactor, documentation, etc.).
Notes on how you tested the change.
Type of Change
Bug fix
New feature
Breaking change
Documentation update
Build / CI / packaging change
Checklist
Code follows the project style (ruff, ty clean).
Tests added or updated and passing locally.
Documentation updated (
docs/and/orREADME.md).A
newsfragments/<PR>.(added|changed|deprecated|removed|fixed|security).mdentry was added, or the PR is explicitly labeledskip-changelog/internal-only.uv.lockregenerated if dependencies changed.
Review Process
Our review process:
Automated checks via GitHub Actions:
actionlinton workflow files.uv auditfor dependency vulnerabilities.ruff(lint + format) andty(type check).pyteston Ubuntu, Windows, and macOS with a coverage floor.Prose checks (codespell, doc8, interrogate) via pre-commit.
Briefcase smoke test on Linux (
create+buildwithout packaging).Documentation build (Sphinx
-W), TSV schema doc drift check, and link check.
Peer review by maintainers.
Discussion of any required changes.
Approval and merge.
Community Guidelines
Code of Conduct
We are committed to providing a welcoming and inclusive environment. Please:
Be respectful and professional.
Welcome newcomers and help them learn.
Focus on constructive feedback.
Assume good intentions.
Be patient with different perspectives.
Communication Channels
GitHub Issues — for bug reports and feature requests.
GitHub Discussions — for general questions and ideas.
Pull Requests — for code, documentation, and CI contributions.
Recognition
Contributors are recognised through:
Author credits in the commit history.
Acknowledgements in release notes and, where appropriate, in publications.
Research Impact
This software is designed for clinical research use. If you use or extend it in your research:
Cite the software in your publications.
Share feedback so we can improve future versions.
Consider contributing improvements back to the upstream repository.
Development Workflow
Branch Strategy
We use a simple trunk-based strategy:
main— integration branch; always releasable.feature/*— feature development branches.fix/*— bug-fix branches.docs/*— documentation-only branches.enh/*— larger enhancement / refactor branches.
Release Process
Maintainers follow a PR-based flow: bump versions and assemble the changelog on a
branch, merge to main, then tag vX.Y.Z and push the tag to publish builds.
Concrete steps:
Update
dbs_annotator.__version__insrc/dbs_annotator/__init__.py(Hatch reads this as the distribution version) and[tool.briefcase].versioninpyproject.toml. These two values must match.Build
CHANGELOG.mdfrom Towncrier fragments (or usescripts/release_prepare.py/ the CD - Prepare release PR workflow), for example:uv run towncrier build --yes --version X.Y.Z --date YYYY-MM-DD
Open a release PR, land it on
main, then push the matchingvX.Y.Ztag.The CD - Create GitHub Release workflow builds Python wheels/sdist and Briefcase installers (Windows MSI, macOS DMG, Linux system package), then creates the GitHub Release with artifacts attached.
Read the Docs publishes the matching versioned documentation from the tag.
See Releasing for more detail (local script, workflow inputs, and tagging).
Continuous Integration
GitHub Actions handles:
Workflow linting (
actionlint).Dependency auditing (
uv audit).Lint, format, and type checking (ruff, ty).
Cross-platform tests (Ubuntu, Windows, macOS) with coverage.
Briefcase ZIP packaging smoke test on Windows.
Documentation build and link check.
Release builds for Python wheels/sdist and Briefcase installers.
Weekly/manual docs health report artifacts (warnings and linkcheck summary).
Manual docs screenshot artifact generation from Qt views.
Specialised Contributions
Clinical Domain Experts
If you are a clinician or DBS specialist:
Share real-world session workflows and edge cases.
Review and suggest improvements to clinical and session scale presets (
CLINICAL_SCALES_PRESETS/SESSION_SCALES_PRESETSinconfig.py).Provide feedback on electrode model definitions and contact diagrams.
Help validate clinical accuracy of exported reports.
GUI / UX Contributors
For contributors with design expertise:
Improve the interaction design of the wizard steps.
Enhance the responsive behaviour on smaller displays.
Test accessibility (keyboard navigation, screen readers, contrast).
Propose visual refinements to the light and dark themes.
Data Scientists
For data-science contributions:
Improve analysis features in the longitudinal report.
Add statistical tooling for outcome analysis.
Enhance the BIDS-compliant TSV schema and export.
Integrate with external analysis pipelines.
Thank You
Thank you for considering contributing to DBS Annotator! Your contributions help make deep brain stimulation research more accessible and reproducible.
For questions about contributing, please open an issue or start a discussion on GitHub.