Contributing to Thesis Imaging Pipeline#
Thank you for your interest in contributing! This document provides guidelines and instructions.
Prerequisites#
Python 3.11+
Git
Conda or venv
FSL and ANTs (for testing preprocessing)
Getting Started#
1. Fork and Clone#
git clone https://gitlab.liu.se/YOUR_USERNAME/thesis.git
cd thesis
git remote add upstream https://gitlab.liu.se/pasje442/thesis.git
2. Create Development Environment#
conda env create -f environment.yml
conda activate thesis
pip install -e ".[dev,docs]"
pre-commit install
3. Create Feature Branch#
git checkout -b feature/my-feature
# or
git checkout -b fix/my-fix
Development Workflow#
Code Style#
We follow PEP 8 with Black formatting:
# Format code
make format
# Check formatting
make lint
# Type checking
make type-check
# Run all checks
make check
Testing#
All code must have tests:
# Run all tests
make test
# Run with coverage
make test-cov
# Run specific test
pytest tests/unit/test_my_test.py::TestClass::test_method -v
Test Coverage Requirement: Aim for >80% coverage on new code.
Commit Messages#
Follow conventional commits:
<type>(<scope>): <subject>
<body>
<footer>
Types:
feat: New featurefix: Bug fixdocs: Documentationtest: Test additions/changesrefactor: Code refactoringperf: Performance improvementsci: CI/CD changes
Example:
feat(preprocessing): add Gibbs ringing artifact removal
Implement PATCH algorithm for Gibbs artifact correction.
Includes comprehensive tests and documentation.
Closes #42
Do not manually edit CHANGELOG.md or bump the version. After your feature
commits land, run make bump (commitizen) to increment the dev version and
update the changelog atomically. Preview with make bump-dry, then push the tag
with git push --follow-tags.
Before Pushing#
# Update from upstream
git fetch upstream
git rebase upstream/main
# Run all checks
make check
# Run tests
make test
# Push
git push origin feature/my-feature
Pull Request Process#
Update Documentation
Add docstrings to new functions
Update relevant documentation files
Add examples if applicable
Add Tests
Unit tests for new functions
Integration tests for pipelines
Test fixtures for common setup
Code Review
Address reviewer feedback
Keep commits clean and logical
Maintain discussion in PR
Merge
Squash commits if requested
Delete feature branch after merge
Adding a New Workflow#
The full decorator-API reference — @workflow / @requires / @produces / @verify,
the path-declaration types, config namespaces, and the inputnode/outputnode
contracts — lives in custom_workflows.md. This section is the
contributor checklist for vendoring a workflow into src/thesis/ (rather than
running it out-of-tree); follow it alongside that guide instead of restating the API here.
Create the package
src/thesis/workflows/my_workflow/.Wire up self-registration. A workflow registers itself the moment its module is imported (the
@workflowdecorator runs at import time), so the package__init__.pymust import the module for its side effect:# src/thesis/workflows/my_workflow/__init__.py """My workflow package.""" from . import workflow as _workflow # noqa: F401 (side effect: registration)
Implement the factory in
workflow.pyusing the decorator API (seecustom_workflows.mdfor the full annotated example, and Owning a config section if the workflow claims its own top-level YAML key). Add a@verify(check_fn)preflight check when the implicit existence checks from@requiresare not enough (e.g. cross-field validation).src/thesis/workflows/atlas/workflow.pyis the reference cohort example.Split large workflows early. Keep
workflow.pyfocused on Nipype graph construction and the decorator stack; move heavier concerns (I/O helpers, parameter models, statistic builders) into private helper modules. The atlas workflow is the reference layout:workflow.py,compute.py,_params.py,_io.py,_statistics.py.Add tests in
tests/unit/(andtests/integration/if external tools are involved). At minimum assert that the module registers and that the factory returns anipype.Workflow:# tests/unit/test_my_workflow.py from thesis.core.context import ProcessingContext from thesis.core.registry import WORKFLOW_REGISTRY # Importing the module triggers @workflow registration. from thesis.workflows.my_workflow import workflow as _my_workflow # noqa: F401 class TestBuildMyWorkflow: def test_registers(self): assert WORKFLOW_REGISTRY.has("my_workflow") def test_returns_nipype_workflow(self, mock_config, tmp_path): ctx = ProcessingContext( patient_id="TEST001", config=mock_config, input_dir=tmp_path, output_dir=tmp_path, ) entry = WORKFLOW_REGISTRY.get("my_workflow") wf = entry.factory(mock_config, ctx) assert wf.name.startswith("my_workflow")
Document. Add Google-style docstrings to the factory and public helpers; add the workflow to
docs/guides/workflows.mdand its “Choosing a workflow” table; add an API reference pagedocs/api/workflows.my_workflow.rstand link it fromdocs/api/workflows.rst.
Vendor into the package, or keep it out-of-tree? The steps above vendor the workflow into
src/thesis/. For experiments or one-off workflows that don’t belong in the package, prefer an out-of-tree script run viathesis run --script ./my_workflow.py— it uses the same decorator API without touching the package. Seecustom_workflows.md, andexamples/plain_nipype_workflow.py+examples/annotated_nipype_workflow.pyfor a before/after pair showing a plain Nipype script alongside its annotated form.
Running Existing Tests#
# All tests
pytest tests/
# Unit tests only (no external tools required)
pytest tests/unit/ -v
# Integration tests (may require FSL / ANTs)
pytest tests/integration/ -v
# Specific test file
pytest tests/unit/test_config_validators.py -v
# Specific test class or method
pytest tests/unit/test_config_validators.py::TestPathConfig::test_defaults -v
# With coverage
pytest tests/ --cov=src/thesis --cov-report=html
# Re-run only the last failures
pytest --lf
# Stop on first failure
pytest -x
Documentation#
Building Docs Locally#
sphinx-build -W -b html docs docs/build/html
open docs/build/html/index.html
Adding Documentation#
Create
.mdor.rstfile indocs/guides/Update
docs/index.rstwith linkBuild and verify locally
Reporting Issues#
Open an issue on the GitLab project (https://gitlab.liu.se/pasje442/thesis/-/issues) and provide:
Clear description
Steps to reproduce
Expected vs actual behavior
Environment (OS, Python version, etc.)
Error messages and logs
Getting Help#
📚 Check the documentation
🐛 Search existing issues on the GitLab project before opening a new one
Code of Conduct#
Our Pledge#
We are committed to providing a welcoming and inspiring community for all.
Standards#
Examples of behavior that contributes to a positive environment:
Using welcoming and inclusive language
Being respectful of different viewpoints
Accepting constructive criticism
Focusing on what’s best for the community
Showing empathy towards others
Unacceptable Behavior#
Including but not limited to:
Harassment or discrimination
Personal attacks
Trolling or insulting comments
Publishing others’ private information
Other conduct that could reasonably be considered inappropriate
Thank you for making this project better! 🎉