Contributing#
Contributing to ultrasound-metrics#
We welcome contributions from the community! This guide explains how to contribute to the project.
Development Setup#
Fork and clone the repository:
git clone https://github.com/yourusername/ultrasound-metrics.git cd ultrasound-metrics
Install development dependencies:
make install
Contributing Workflow#
1. Create a Feature Branch#
git checkout -b feature/your-feature-name
2. Make Your Changes#
Follow the coding standards (see below)
Add tests for new functionality
Update documentation as needed
3. Test Your Changes#
# Run linting
make check
# Run tests
make test
# Build documentation
make docs
4. Submit a Pull Request#
Push your branch to your fork
Create a pull request with a clear description
Link any relevant issues
Coding Standards#
Type Annotations#
All public functions should have complete type annotations:
from jaxtyping import Float, Complex, jaxtyped
from beartype import beartype as typechecker
@jaxtyped(typechecker=typechecker)
def new_metric(
data: Complex[ArrayAPIObj, "elements *dims"],
param: float = 1.0,
) -> Float[ArrayAPIObj, "*dims"]:
"""Clear docstring with parameters and returns sections."""
If you’re not sure how to use jaxtyping,
feel free to open a draft PR and tag a maintainer for help.
Array API Compliance#
Use
array_namespace()to detect backendImplement using Array API standard functions when possible
Avoid backend-specific operations
See array_api_design.md for more context
from array_api_compat import array_namespace
def new_metric(data):
xp = array_namespace(data)
# Use xp.* operations for backend compatibility
return xp.mean(xp.abs(data)**2)
Documentation#
Docstring Format#
Use NumPy-style docstrings:
def coherence_factor(channel_images, power_based=True):
"""Compute the coherence factor of beamformed ultrasound data.
The coherence factor measures the degree of coherence between signals
received from different elements.
Parameters
----------
channel_images : array_like, shape (receive_elements, *img_dims)
Complex-valued beamformed data before summation across receive elements.
power_based : bool, optional
If True, uses power-based coherence. Default is True.
Returns
-------
coherence : array_like, shape (*img_dims)
Coherence factor values ranging from 0 to 1.
References
----------
.. [1] Hollman, K. W., et al. (1999). Coherence factor of speckle from
a multi-row probe. IEEE Ultrasonics Symposium.
"""
Mathematical Formulations#
Try to include precise mathematical descriptions:
def gcnr(values_inside, values_outside):
"""Compute the Generalized Contrast-to-Noise Ratio.
The GCNR is defined as:
.. math::
GCNR = 1 - \\sum_x \\min\\{f_1(x), f_2(x)\\}
where f_1 and f_2 are the normalized histograms of the inside
and outside regions, respectively.
"""
These will get rendered in the API documentation.
References#
Include literature references for published metrics.
e.g.
"""
Reference:
----------
A. Rodriguez-Molares, O. M. Hoel Rindal, J. D'hooge, S. -E. Måsøy, A. Austeng
and H. Torp, "The Generalized Contrast-to-Noise Ratio," 2018 IEEE International
Ultrasonics Symposium (IUS), Kobe, Japan, 2018, pp. 1-4,
doi: 10.1109/ULTSYM.2018.8580101.
""""
Testing#
Test Structure#
Place tests in
tests/directory matching source structureUse pytest for all testing
Test edge cases (empty arrays, single values, 0-values, etc.)
Test across multiple backends when applicable
Compare against reference implementations when avaialble
Backend Testing#
For now, we use the scipy.conftest backend iterator to test all installed array backends.
It provides the skip_xp_backends option to skip unsupported array libraries.
import pytest
from scipy.conftest import array_api_compatible, skip_xp_backends # noqa: F401
from ultrasound_metrics.metrics.gcnr import gcnr
@pytest.mark.skip_xp_backends("array_api_strict", reason="Array-API v2024.12 does not define histogram.")
@pytest.mark.usefixtures("skip_xp_backends")
@array_api_compatible
def test_gcnr_synthetic_data(xp):
"""Test gCNR calculation with synthetic data simulating a hypoechoic lesion."""
n_samples = 1000
# ...
Test Categories#
Unit tests: Individual function behavior
Backend tests: Consistency across array libraries
Performance tests: optionally show GPU acceleration