# Developer Guide This guide provides detailed information for developers working on TRX-Python. ```{toctree} :maxdepth: 1 contributing ``` ## Installation for Development ### Prerequisites - Python 3.11 or later (Python 3.12+ recommended) - Git - pip ### Setting Up Your Environment 1. **Clone the repository**: ```bash # If you're a contributor, fork first then clone your fork git clone https://github.com/YOUR_USERNAME/trx-python.git cd trx-python ``` 2. **Install with all development dependencies**: ```bash pip install -e ".[all]" ``` This installs: - Core dependencies (numpy, nibabel, deepdiff, typer) - Development tools (spin, setuptools_scm) - Documentation tools (sphinx, numpydoc) - Style tools (ruff, pre-commit) - Testing tools (pytest, pytest-cov) 3. **Set up the development environment**: ```bash spin setup ``` This command: - Adds upstream remote if missing - Fetches version tags for correct `setuptools_scm` version detection ## Using Spin We use [spin](https://github.com/scientific-python/spin) for development workflow. Spin provides a consistent interface for common development tasks. ### Available Commands Run `spin` without arguments to see all available commands: ```bash spin ``` **Setup Commands:** ```bash spin setup # Configure development environment ``` **Build Commands:** ```bash spin install # Install package in editable mode ``` **Test Commands:** ```bash spin test # Run all tests spin test -m NAME # Run tests matching pattern spin test -v # Verbose output spin lint # Run ruff linting spin lint --fix # Auto-fix linting issues ``` **Documentation Commands:** ```bash spin docs # Build documentation spin docs --clean # Clean and rebuild spin docs --open # Build and open in browser ``` **Cleanup Commands:** ```bash spin clean # Remove temporary files and build artifacts ``` ## Code Quality ### Linting with Ruff We use [ruff](https://docs.astral.sh/ruff/) for linting and formatting. Configuration is in `ruff.toml`. ```bash # Check for issues spin lint # Auto-fix issues spin lint --fix # Format code ruff format . # Check formatting without changes ruff format --check . ``` ### Pre-commit Hooks We recommend using pre-commit hooks to catch issues before committing: ```bash # Install pre-commit hooks pre-commit install # Run hooks manually on all files pre-commit run --all-files ``` The hooks run: - `ruff` - Linting with auto-fix - `ruff-format` - Code formatting - `codespell` - Spell checking ## Testing ### Running Tests ```bash # Run all tests spin test # Run tests matching a pattern spin test -m memmap # Run with pytest directly pytest trx/tests # Run with coverage pytest trx/tests --cov=trx --cov-report=term-missing ``` ### Test Data Test data is automatically downloaded from Figshare on first run. Data is cached in `~/.tee_ar_ex/`. You can manually fetch test data: ```python from trx.fetcher import fetch_data, get_testing_files_dict fetch_data(get_testing_files_dict()) ``` ### Writing Tests - Tests go in `trx/tests/` - Use pytest fixtures for setup/teardown - Use `pytest.mark.skipif` for conditional tests Example: ```python import pytest import numpy as np from numpy.testing import assert_array_equal def test_my_function(): result = my_function(input_data) expected = np.array([1, 2, 3]) assert_array_equal(result, expected) @pytest.mark.skipif(not dipy_available, reason="Dipy required") def test_with_dipy(): # Test that requires dipy pass ``` ## Documentation ### Building Documentation ```bash # Build docs spin docs # Clean build spin docs --clean # Build and open in browser spin docs --open ``` Documentation is built with Sphinx and uses: - `pydata-sphinx-theme` for styling - `sphinx-autoapi` for API documentation - `numpydoc` for NumPy-style docstrings ### Writing Documentation - Source files are in `docs/source/` - Use MyST Markdown format - API docs are auto-generated from docstrings ### NumPy Docstring Format All functions and classes should be documented using NumPy-style docstrings: ```python def load(filename, reference=None): """Load a tractogram file. Parameters ---------- filename : str Path to the tractogram file. reference : str, optional Path to reference anatomy for formats that require it. Returns ------- tractogram : TrxFile or StatefulTractogram The loaded tractogram. Raises ------ ValueError If the file format is not supported. See Also -------- save : Save a tractogram to file. Examples -------- >>> from trx.io import load >>> trx = load("tractogram.trx") """ pass ``` ## Project Structure ```text trx-python/ ├── trx/ # Main package │ ├── __init__.py │ ├── cli.py # Command-line interface (Typer) │ ├── fetcher.py # Test data fetching │ ├── io.py # Unified I/O interface │ ├── streamlines_ops.py # Streamline operations │ ├── trx_file_memmap.py # Core TrxFile class │ ├── utils.py # Utility functions │ ├── viz.py # Visualization (optional) │ ├── workflows.py # High-level workflows │ └── tests/ # Test suite ├── docs/ # Documentation │ └── source/ ├── .github/ # GitHub Actions workflows │ └── workflows/ ├── .spin/ # Spin configuration │ └── cmds.py ├── pyproject.toml # Project configuration ├── ruff.toml # Ruff configuration └── .pre-commit-config.yaml # Pre-commit hooks ``` ## Continuous Integration GitHub Actions runs on every push and pull request: - **test.yml**: Runs tests on Python 3.11-3.13 across Linux, macOS, Windows - **codeformat.yml**: Checks code formatting with pre-commit/ruff - **coverage.yml**: Generates code coverage reports - **docbuild.yml**: Builds and deploys documentation ## Environment Variables ### TRX_TMPDIR Controls where temporary files are stored during memory-mapped operations. ```bash # Use a specific directory export TRX_TMPDIR=/path/to/tmp # Use current working directory export TRX_TMPDIR=use_working_dir ``` Default: System temp directory (`/tmp` on Linux/macOS, `C:\WINDOWS\Temp` on Windows) ## Release Process Releases are managed via GitHub: 1. Update version in `pyproject.toml` if needed 2. Create a GitHub release with appropriate tag 3. CI automatically publishes to PyPI ### Version Detection We use `setuptools_scm` for automatic version detection from git tags. This requires: - Proper git tags from upstream - Running `spin setup` after cloning a fork