Development Setup
This guide will help you set up a development environment for contributing to Easy PMF.
Prerequisites
- Python 3.9 or later
- Git
- uv (recommended) or pip
Setting Up Development Environment
1. Clone the Repository
2. Set Up Python Environment
Using uv (Recommended)
# Install uv if you haven't already
curl -LsSf https://astral.sh/uv/install.sh | sh
# Create and activate virtual environment with dependencies
uv sync
# Activate the environment
source .venv/bin/activate # On Windows: .venv\Scripts\activate
Using pip and venv
# Create virtual environment
python -m venv easy_pmf_env
source easy_pmf_env/bin/activate # On Windows: easy_pmf_env\Scripts\activate
# Install development dependencies
pip install -e ".[dev]"
3. Verify Installation
# Run tests to verify everything works
uv run pytest
# Check code style
uv run ruff check
# Run type checking
uv run mypy .
# Test CLI
easy-pmf --version
Development Workflow
1. Code Quality Tools
Easy PMF uses several tools to maintain code quality:
Ruff (Linting and Formatting)
# Check for linting issues
uv run ruff check
# Fix auto-fixable issues
uv run ruff check --fix
# Format code
uv run ruff format
MyPy (Type Checking)
# Run type checking
uv run mypy .
# Run type checking on specific file
uv run mypy src/easy_pmf/pmf.py
Pre-commit Hooks (Optional)
Set up pre-commit hooks to automatically check code before commits:
2. Testing
Running Tests
# Run all tests
uv run pytest
# Run tests with coverage
uv run pytest --cov=easy_pmf --cov-report=html
# Run specific test file
uv run pytest tests/test_pmf.py
# Run specific test
uv run pytest tests/test_pmf.py::test_pmf_basic_functionality
Writing Tests
Create test files in the tests/ directory:
# tests/test_new_feature.py
import pytest
import pandas as pd
from easy_pmf import PMF
def test_new_feature():
"""Test description."""
# Create test data
concentrations = pd.DataFrame({
'Species1': [1.0, 2.0, 3.0],
'Species2': [2.0, 4.0, 6.0]
})
# Test your feature
pmf = PMF(n_components=2)
pmf.fit(concentrations)
# Assertions
assert pmf.converged_
assert pmf.contributions_.shape == (3, 2)
3. Documentation
Building Documentation
# Install documentation dependencies
pip install -e ".[docs]"
# Build documentation
mkdocs build
# Serve documentation locally
mkdocs serve
# Open http://127.0.0.1:8000 in your browser
Writing Documentation
- Use Google-style docstrings in code
- Add examples to docstrings
- Update relevant
.mdfiles indocs/ - Include type hints
Example docstring:
def new_function(data: pd.DataFrame, n_components: int = 5) -> PMF:
"""Short description of the function.
Longer description explaining what the function does,
its use cases, and any important details.
Args:
data: Input concentration data with samples as rows and species as columns.
n_components: Number of PMF factors to extract. Defaults to 5.
Returns:
Fitted PMF model instance.
Raises:
ValueError: If data contains negative values.
Examples:
Basic usage:
>>> import pandas as pd
>>> from easy_pmf import PMF
>>> data = pd.DataFrame({'A': [1, 2, 3], 'B': [2, 4, 6]})
>>> pmf = new_function(data, n_components=2)
>>> pmf.converged_
True
"""
Project Structure
easy-pmf/
├── src/
│ └── easy_pmf/
│ ├── __init__.py # Main PMF class
│ └── cli.py # Command-line interface
├── tests/
│ ├── test_pmf.py # PMF class tests
│ └── test_cli.py # CLI tests
├── docs/
│ ├── index.md # Documentation home
│ ├── getting-started/ # Getting started guides
│ ├── user-guide/ # User guides
│ ├── api/ # API reference
│ └── examples/ # Examples
├── data/ # Example datasets
├── pyproject.toml # Project configuration
├── mkdocs.yml # Documentation configuration
├── README.md # Project overview
└── CHANGELOG.md # Version history
Adding New Features
1. Planning
Before implementing:
- Check existing issues on GitHub
- Open a discussion for major features
- Create an issue describing the feature
- Get feedback from maintainers
2. Implementation Steps
-
Create a branch:
-
Implement the feature:
- Write code following existing patterns
- Add type hints
- Include docstrings
-
Handle edge cases
-
Add tests:
- Test normal usage
- Test edge cases
- Test error conditions
-
Aim for >90% coverage
-
Update documentation:
- Add docstrings to new functions/classes
- Update relevant documentation files
-
Add examples if applicable
-
Test everything:
3. Example: Adding a New Method
# In src/easy_pmf/__init__.py
class PMF:
# ... existing methods ...
def validate_results(self, threshold: float = 0.1) -> Dict[str, bool]:
"""Validate PMF results using various criteria.
Args:
threshold: Validation threshold for various checks.
Returns:
Dictionary with validation results.
Examples:
>>> pmf = PMF(n_components=5)
>>> pmf.fit(concentrations, uncertainties)
>>> validation = pmf.validate_results()
>>> validation['converged']
True
"""
if self.contributions_ is None:
raise ValueError("Model must be fitted before validation")
validation = {
'converged': self.converged_,
'reasonable_contributions': (self.contributions_ >= 0).all().all(),
'reasonable_profiles': (self.profiles_ >= 0).all().all(),
}
return validation
Development Guidelines
Code Style
- Follow PEP 8 with line length of 88 characters
- Use type hints for all function parameters and returns
- Write descriptive variable names
- Keep functions focused and reasonably sized
- Use docstrings for all public functions and classes
Git Workflow
-
Use descriptive commit messages:
-
Keep commits focused on single changes
- Rebase before submitting pull requests
- Update CHANGELOG.md for significant changes
Testing Guidelines
- Test all public APIs
- Include edge cases
- Test error conditions
- Use meaningful test names
- Keep tests independent
Documentation Guidelines
- Use Google-style docstrings
- Include examples in docstrings
- Update user guides for new features
- Add API documentation for new classes/functions
- Keep documentation up to date
Common Development Tasks
Adding a New Dataset
- Add data files to
data/directory - Update example documentation
- Add tests for loading the dataset
- Update CLI if needed
Improving Algorithm Performance
- Profile current performance
- Implement improvements
- Add benchmarks
- Ensure backward compatibility
Adding Visualization Features
- Design API for new plots
- Implement plotting functions
- Add to visualization guide
- Include examples
Getting Help
- GitHub Discussions: For questions and ideas
- GitHub Issues: For bugs and feature requests
- Code Review: Submit pull requests for feedback
- Documentation: Check existing docs and examples
Next Steps
- Read the Contributing Guidelines
- Learn about Testing practices
- Check out existing Issues
- Join the community discussions