Contributing¶
Thank you for your interest in contributing to SenoQuant. This guide helps you set up a development environment and follow the project workflow.
Development setup¶
Environment creation¶
Use the setup script for your operating system from the repository root:
# Windows
.\scripts\development\setup_windows.ps1
# macOS
bash scripts/development/setup_macos.sh
# Linux
bash scripts/development/setup_linux.sh
The scripts install Python 3.11, Java support, napari, test dependencies, and SenoQuant in editable mode. See the development installation guide for prerequisites, custom environment names, and Windows ARM64 behavior.
Verify installation¶
Launch napari and open the plugin from the Plugins menu.
napari
Select Plugins -> SenoQuant to verify the plugin loads correctly.
Testing¶
Running tests¶
The project uses pytest with an 80% coverage requirement.
conda activate senoquant-dev
pytest
Test configuration¶
- Config file:
pytest.inispecifies coverage thresholds and test discovery. - Fixtures:
tests/conftest.pyprovides stubs for headless GUI dependencies (DummySignal and mock napari layers). - Coverage: Tests require >=80% line coverage to pass.
Writing tests¶
When adding new functionality:
- Create test modules in the corresponding
tests/subdirectory. - Use fixtures from
conftest.pyfor napari layer mocks. - Leverage
tmp_pathfor isolated file operations. - Mock external dependencies (BioIO and Qt signals) where appropriate.
Example test structure:
def test_new_feature(tmp_path):
# Arrange.
test_file = tmp_path / "test.tif"
test_file.write_bytes(b"fake data")
# Act.
result = my_function(test_file)
# Assert.
assert result is not None
Headless testing¶
Tests run without a display server.
- Qt dependencies are stubbed in
conftest.py. - Avoid importing GUI modules at top level in test files.
- Use
pytest-qtfor Qt-specific testing when needed.
Documentation¶
Building documentation locally¶
Install documentation dependencies.
pip install -r docs/requirements.txt
Serve documentation locally for live preview.
mkdocs serve
Visit http://127.0.0.1:8000 to view the docs.
Build the static site.
mkdocs build
Build strictly before publishing changes.
mkdocs build --strict
Versioned documentation¶
Published documentation is versioned with mike.
- Pushes to
mainormasterpublish thedevdocumentation version. - Published GitHub releases publish the release tag as an immutable docs version, strip the
senoquant-vprefix from the tag name, update thelatestalias, and makelatestthe default route forhttps://haamsree.github.io/senoquant/. - The version selector shows
devabove ordinary release versions. The newest release is marked with thelatestalias in the selector. - Manual runs of the Docs workflow can backfill a version or move aliases through the workflow inputs.
Use mike serve when you need to preview the version selector locally.
Do not use mkdocs gh-deploy; it bypasses the version manifest and aliases managed by mike.
Documentation structure¶
- User guide (
docs/user/): End-user documentation for each plugin tab. - Developer guide (
docs/developer/): Architecture, models, features, and contribution details. - API reference (
docs/api/): Auto-generated via mkdocstrings (do not edit manually).
Writing documentation¶
- Use Markdown with Material for MkDocs extensions.
- Include code examples with proper syntax highlighting.
- Add screenshots to
docs/assets/for UI documentation. - Reference specific line numbers when linking to code, for example:
[file.py](file.py#L10).
Code conventions¶
Style guidelines¶
- Type hints: Use modern Python 3.11+ type annotations.
- Docstrings: Use NumPy style for public APIs.
- Imports: Use absolute imports from
senoquant. - File paths: Use
pathlib.Pathinstead of string paths.
Architecture patterns¶
- Frontend/backend split: Each tab has
frontend.py(Qt UI) andbackend.py(pure logic). - Settings schema: For segmentation/spots, keep
details.jsoncompatible withsrc/senoquant/utils/model_details.schema.json. - Model discovery:
- Segmentation/spots use
models/<name>/details.json+model.py. - Prediction uses
models/<name>/model.py(nodetails.jsonrequired). - Dataclasses: Use
@dataclass(slots=True)for config objects.
Naming conventions¶
- Segmentation outputs:
<image>_<model>_nuc_labelsor<image>_<model>_cyto_labels. - Spot outputs:
<image>_<detector>_spot_labels. - Private methods: Prefix with
_(for example,_compute_internal()). - Signals: Qt signals use past tense (for example,
segmentation_completedanderror_occurred).
Dependencies¶
Core dependencies¶
- napari: Not pinned in
pyproject.toml; install separately. - Qt: Via QtPy (supports PyQt5, PyQt6, PySide2, and PySide6).
- BioIO: Format-agnostic image reader with 50+ plugins.
- ONNX Runtime: For StarDist model inference.
Optional dependencies¶
Defined in pyproject.toml:
.[all]: Full stack including napari and optional dependencies.
Extending SenoQuant¶
Segmentation model¶
- Create folder:
src/senoquant/tabs/segmentation/models/my_model/. - Add metadata:
details.jsonwith model info, tasks, and settings. - Implement logic:
model.pysubclassingSenoQuantSegmentationModel. - Test: Verify the model appears in the Segmentation tab dropdown.
See Models & Detectors for the detailed guide.
Spot detector¶
Use the same pattern as segmentation models under src/senoquant/tabs/spots/models/.
Prediction model¶
- Create folder:
src/senoquant/tabs/prediction/models/my_model/. - Implement logic:
model.pysubclassingSenoQuantPredictionModel. - Provide UI hooks: implement
build_widget()+collect_widget_settings(). - Return layers: implement
run()to return napari-compatible layer specs.
See Prediction models for the detailed guide.
Quantification feature¶
- Create module:
src/senoquant/tabs/quantification/features/my_feature/. - Define data class: Subclass
FeatureDatafor configuration state. - Implement feature: Subclass
SenoQuantFeaturewithbuild()andexport()methods. - Register: Add to
FEATURE_DATA_FACTORYinfeatures/__init__.py. - Batch settings bundles: Update batch feature serialize/deserialize cases in
src/senoquant/tabs/batch/config.py.
See Quantification features for the detailed guide.
Visualization plot¶
- Create module:
src/senoquant/tabs/visualization/plots/my_plot.py. - Define plot class: Subclass
SenoQuantPlotwithplot_typeandorder. - Implement output: Write files in
plot(temp_dir, input_path, export_format, ...). - Register typed data: Add custom
PlotDataclass toPLOT_DATA_FACTORYwhen needed. - Test: Add handler and backend tests under
tests/senoquant/tabs/visualization/.
See Visualization tab for implementation details.
New tab¶
Create a new tab package under src/senoquant/tabs/, export it from src/senoquant/tabs/__init__.py, and wire it into src/senoquant/_widget.py.
See Adding tabs for the full wiring checklist.
Submitting changes¶
Pull request checklist¶
- [ ] Tests pass locally (
pytest). - [ ] Code follows style conventions.
- [ ] New features have test coverage.
- [ ] Documentation is updated (user docs, docstrings, and developer guides).
- [ ] No breaking changes to the batch config format (maintain backward compatibility).
Commit messages¶
Use descriptive commit messages.
Improve U-FISH spot detector threshold behavior
- Adjust threshold handling for edge cases.
- Update detector settings help text.
- Add regression tests for low-signal images.
Common pitfalls¶
- Protobuf version conflicts: Reinstall protobuf after TensorFlow when doing ONNX conversion.
- Headless testing:
conftest.pystubs handle missing Qt/napari; avoid top-level GUI imports in test files. - Model not discovered:
- Segmentation/Spots: check folder naming and confirm
details.jsonexists. - Prediction: check folder naming and confirm
model.pydefines aSenoQuantPredictionModelsubclass. - Batch quantification failures: Verify the
BatchViewershim has correct layer names.
Getting help¶
- GitHub issues: Report bugs or request features.
- Discussions: Ask questions or share use cases.
- Documentation: Consult the user and developer guides.
License¶
SenoQuant is released under the BSD 3-Clause License. By contributing, you agree to license your contributions under the same license.