Thank you for your interest in contributing to mne-denoise! This guide will help you get started with contributing code, documentation, or bug reports.
- Code of Conduct
- Getting Started
- Development Environment
- Workflow
- Code Style
- Testing
- Documentation
- Submitting Changes
- Issue Guidelines
This project follows the MNE-Python Code of Conduct. By participating, you are expected to uphold this code.
- Python 3.10 or higher
- Git
- A GitHub account
-
Fork the repository on GitHub by clicking the "Fork" button.
-
Clone your fork locally:
git clone https://github.com/<your-username>/mne-denoise.git cd mne-denoise
-
Add the upstream remote:
git remote add upstream https://github.com/mne-tools/mne-denoise.git
We recommend using a virtual environment for development.
# Create virtual environment
python -m venv .venv
# Activate it
# On macOS/Linux:
source .venv/bin/activate
# On Windows:
.venv\Scripts\activate
# Upgrade pip
python -m pip install --upgrade pip
# Install in editable mode with all dev dependencies
pip install -e ".[dev,docs]"
# Install pre-commit hooks
pre-commit install# Create environment
conda create -n mne-denoise python=3.12
conda activate mne-denoise
# Install in editable mode
pip install -e ".[dev,docs]"
pre-commit installAlways create a new branch for your work:
# Sync with upstream first
git fetch upstream
git checkout main
git merge upstream/main
# Create feature branch
git checkout -b feature/my-new-feature
# or for bug fixes:
git checkout -b fix/issue-123- Write clean, readable code
- Follow the code style guidelines (see below)
- Add tests for new functionality
- Update documentation as needed
Write clear, descriptive commit messages:
git add .
git commit -m "Add support for custom frequency bands in BandpassBias"Commit message guidelines:
- Use present tense ("Add feature" not "Added feature")
- Use imperative mood ("Move cursor to..." not "Moves cursor to...")
- Keep the first line under 72 characters
- Reference issues when relevant ("Fix #123: ...")
git fetch upstream
git rebase upstream/mainWe use towncrier to manage our changelog. This prevents merge conflicts and ensures standardized release notes.
When you create a Pull Request, please add a changelog entry file in docs/changes/devel/. The file name should be the change type (e.g., feature.rst, bugfix.rst).
For detailed instructions and available types, see docs/changes/README.md.
Author Attribution: We encourage contributors to include their name in the changelog entry if they wish to be highlighted. In Markdown, you can link to your GitHub profile (e.g., ... (by [@YourUser](...))).
We use Ruff for linting and formatting, configured to follow PEP 8 with NumPy docstring conventions.
Pre-commit hooks will automatically format your code on commit. To run manually:
# Check for linting errors
ruff check .
# Auto-fix linting errors
ruff check . --fix
# Format code
ruff format .
# Run all pre-commit hooks
pre-commit run --all-filesWe use NumPy-style docstrings. Example:
def compute_dss(data, bias, n_components=None):
"""Compute DSS spatial filters.
Parameters
----------
data : ndarray, shape (n_channels, n_times)
Input data matrix.
bias : LinearDenoiser
Bias function that emphasizes signal of interest.
n_components : int, optional
Number of components to return. If None, returns all.
Returns
-------
filters : ndarray, shape (n_channels, n_components)
Spatial filters sorted by eigenvalue.
eigenvalues : ndarray, shape (n_components,)
Corresponding eigenvalues.
Examples
--------
>>> from mne_denoise.dss import compute_dss, AverageBias
>>> filters, eigenvalues = compute_dss(data, AverageBias())
See Also
--------
DSS : Scikit-learn compatible transformer.
References
----------
.. [1] de Cheveigné, A., & Simon, J. Z. (2008). Denoising based on
spatial filtering. Journal of Neuroscience Methods.
"""We use pytest for testing. All new code should have tests.
# Run all tests
pytest
# Run with coverage
pytest --cov=mne_denoise --cov-report=html
# Run specific test file
pytest tests/test_linear_dss.py
# Run specific test
pytest tests/test_linear_dss.py::test_dss_epochs -v
# Run tests matching a pattern
pytest -k "zapline" -v- Place tests in the
tests/directory - Name test files
test_*.py - Name test functions
test_* - Use descriptive test names that explain what is being tested
- Use fixtures for common setup
- Plotting tests use the non-interactive Matplotlib backend configured in
tests/conftest.py, and figures are closed automatically after each test - Pass
show=Falsewhen testing plotting functions - For optional dependencies, prefer
pytest.importorskip(...)
Example test:
import numpy as np
import pytest
from mne_denoise.dss import DSS, AverageBias
@pytest.fixture
def sample_epochs():
"""Create sample epochs for testing."""
rng = np.random.default_rng(42)
return rng.standard_normal((10, 32, 1000))
def test_dss_fit_transform_returns_correct_shape(sample_epochs):
"""Test that DSS returns sources with expected shape."""
dss = DSS(bias=AverageBias(), n_components=5)
sources = dss.fit_transform(sample_epochs)
assert sources.shape[0] == 5 # n_components
assert sources.shape[1] == sample_epochs.shape[2] # n_times- Aim for 100% coverage on new code
- The CI will report coverage; check the Codecov report on your PR
- View local coverage report:
open htmlcov/index.html
Documentation is built with Sphinx and hosted on GitHub Pages.
# Build HTML documentation
make -C docs html
# View in browser
open docs/_build/html/index.html # macOS
xdg-open docs/_build/html/index.html # Linux
start docs/_build/html/index.html # Windowsdocs/api.rst- API reference (auto-generated from docstrings)docs/getting-started.rst- Installation and quick startdocs/dss.md- DSS module guideexamples/- Gallery examples (rendered by sphinx-gallery)
Examples are Python scripts in the examples/ directory:
- Create a file with prefix
plot_(e.g.,plot_my_example.py) - Follow the sphinx-gallery format with docstring headers
- Examples are automatically built and included in the gallery
Example template:
"""
Title of Example
================
Brief description of what this example demonstrates.
"""
# %%
# Section Header
# --------------
# Explanation text...
import mne_denoise
# Your code here...-
Push your branch to your fork:
git push origin feature/my-new-feature
-
Open a Pull Request on GitHub against the
mainbranch. -
Fill out the PR template with:
- Description of changes
- Related issue(s)
- Type of change
- Checklist items
-
Wait for CI to complete. All checks must pass.
-
Address review feedback by pushing additional commits.
-
Squash and merge once approved (maintainers will do this).
Before submitting, ensure:
- Code follows the project style (
ruff check .passes) - Code is formatted (
ruff format .produces no changes) - All tests pass (
pytestexits cleanly) - New code has tests with good coverage
- Documentation is updated if needed
- Documentation builds cleanly (
make -C docs html) - CHANGELOG.md is updated for user-facing changes
- Commit messages are clear and descriptive
When reporting a bug, please include:
- Description: What happened vs. what you expected
- Reproduction steps: Minimal code to reproduce the issue
- Environment: Python version, OS, package versions
- Error message: Full traceback if applicable
Use the bug report template when creating an issue.
For feature requests:
- Check if it already exists or is planned
- Describe the use case and motivation
- Provide examples of how it would be used
- Consider if you'd like to implement it yourself
- Open a Discussion for questions
- Check existing issues and discussions first
- Join the MNE-Python community
Thank you for contributing!