Contributing
Contributing to Gospel
We welcome contributions to Gospel! This guide will help you get started with contributing to the project, whether you’re fixing bugs, adding features, improving documentation, or extending the framework with new domains.
Table of Contents
- Getting Started
- Development Setup
- Contributing Guidelines
- Code Standards
- Testing
- Documentation
- Extending Gospel
- Community
Getting Started
Ways to Contribute
- Bug Reports: Help us identify and fix issues
- Feature Requests: Suggest new capabilities or improvements
- Code Contributions: Implement new features or fix bugs
- Documentation: Improve guides, examples, and API documentation
- Domain Extensions: Add new genomic analysis domains
- Testing: Improve test coverage and quality assurance
Before You Start
- Check existing issues and pull requests
- Read our Code of Conduct
- Join our discussion forum for questions
Development Setup
Prerequisites
- Python 3.9 or higher
- Git
- Virtual environment tool (venv, conda, or virtualenv)
Setup Instructions
# 1. Fork and clone the repository
git clone https://github.com/YOUR_USERNAME/gospel.git
cd gospel
# 2. Create development environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# 3. Install development dependencies
pip install -e .
pip install -r requirements-dev.txt
# 4. Setup pre-commit hooks
pre-commit install
# 5. Download test databases
python scripts/setup_test_databases.py
# 6. Run tests to verify setup
pytest tests/
Development Dependencies
The development environment includes:
- Testing: pytest, pytest-cov, pytest-mock
- Code Quality: black, flake8, mypy, pre-commit
- Documentation: sphinx, sphinx-rtd-theme
- Development Tools: jupyter, ipython, tox
Contributing Guidelines
Issue Reporting
When reporting bugs or requesting features:
**Bug Report Template:**
**Describe the bug**
A clear description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Run command '...'
2. With input file '...'
3. See error
**Expected behavior**
What you expected to happen.
**Environment:**
- OS: [e.g. Ubuntu 20.04]
- Python version: [e.g. 3.9.7]
- Gospel version: [e.g. 1.2.3]
**Additional context**
Any other context about the problem.
Pull Request Process
- Create a branch from
main
for your changes:git checkout -b feature/your-feature-name
-
Make your changes following our code standards
-
Add tests for new functionality
-
Update documentation if needed
- Run the test suite:
pytest tests/ black gospel/ flake8 gospel/ mypy gospel/
- Commit your changes with descriptive messages:
git commit -m "feat: add new pharmacogenetic pathway analysis"
- Push to your fork and create a pull request
Commit Message Format
We follow conventional commit format:
type(scope): description
[optional body]
[optional footer]
Types:
feat
: New featurefix
: Bug fixdocs
: Documentation changesstyle
: Code style changes (formatting, etc.)refactor
: Code refactoringtest
: Adding or updating testschore
: Maintenance tasks
Examples:
feat(fitness): add muscle fiber type analysis
fix(cli): resolve VCF parsing error for large files
docs(api): update domain analyzer documentation
Code Standards
Python Style Guide
We follow PEP 8 with some modifications:
# Use black for automatic formatting
black gospel/
# Line length: 88 characters (black default)
# Use type hints for all public functions
def analyze_variants(variants: List[Variant]) -> AnalysisResults:
"""Analyze genetic variants."""
pass
# Use docstrings for all public functions
def calculate_score(variant: Variant) -> float:
"""
Calculate variant impact score.
Args:
variant: Genetic variant to score
Returns:
Impact score between 0.0 and 1.0
Raises:
ValueError: If variant data is invalid
"""
pass
Code Organization
gospel/
├── core/ # Core functionality
│ ├── variant.py # Variant data structures
│ ├── scoring.py # Scoring algorithms
│ └── analysis.py # Main analysis engine
├── domains/ # Domain-specific analyzers
│ ├── fitness.py # Fitness domain
│ ├── pharmacogenetics.py # Pharmacogenetics domain
│ └── nutrition.py # Nutrition domain
├── llm/ # AI/LLM integration
├── cli/ # Command-line interface
├── utils/ # Utility functions
└── tests/ # Test suite
Error Handling
# Use specific exception types
class GospelError(Exception):
"""Base exception for Gospel errors."""
pass
class VariantProcessingError(GospelError):
"""Error in variant processing."""
pass
# Provide helpful error messages
def process_vcf(vcf_file: str) -> List[Variant]:
if not os.path.exists(vcf_file):
raise FileNotFoundError(f"VCF file not found: {vcf_file}")
try:
# Process VCF
pass
except Exception as e:
raise VariantProcessingError(
f"Failed to process VCF file {vcf_file}: {e}"
) from e
Testing
Test Structure
tests/
├── unit/ # Unit tests
│ ├── test_variant.py
│ ├── test_scoring.py
│ └── test_domains/
├── integration/ # Integration tests
│ ├── test_cli.py
│ └── test_analysis.py
├── fixtures/ # Test data
│ ├── sample.vcf
│ └── expected_results.json
└── conftest.py # Pytest configuration
Writing Tests
import pytest
from gospel.core.variant import Variant
from gospel.domains.fitness import FitnessAnalyzer
class TestFitnessAnalyzer:
"""Test fitness domain analysis."""
def test_sprint_analysis(self):
"""Test sprint performance analysis."""
# Arrange
analyzer = FitnessAnalyzer()
variant = Variant(
id="rs1815739",
gene="ACTN3",
genotype="RR"
)
# Act
result = analyzer.analyze_sprint_performance([variant])
# Assert
assert result.sprint_score > 0.8
assert "power" in result.advantages
@pytest.mark.parametrize("genotype,expected_score", [
("RR", 0.9),
("RX", 0.6),
("XX", 0.3)
])
def test_actn3_scoring(self, genotype, expected_score):
"""Test ACTN3 variant scoring."""
analyzer = FitnessAnalyzer()
variant = Variant(id="rs1815739", genotype=genotype)
score = analyzer.score_actn3_variant(variant)
assert abs(score - expected_score) < 0.1
Running Tests
# Run all tests
pytest
# Run with coverage
pytest --cov=gospel
# Run specific test file
pytest tests/unit/test_variant.py
# Run tests matching pattern
pytest -k "test_fitness"
# Run tests with verbose output
pytest -v
Documentation
Documentation Standards
- Use clear, concise language
- Include code examples for all public APIs
- Provide real-world use cases
- Keep documentation up-to-date with code changes
Building Documentation
# Install documentation dependencies
pip install -r docs/requirements.txt
# Build HTML documentation
cd docs/
make html
# Serve documentation locally
python -m http.server 8000 -d _build/html/
Documentation Types
- API Documentation: Docstrings in code
- User Guides: Step-by-step tutorials
- Reference: Complete API and CLI reference
- Examples: Real-world use cases
Extending Gospel
Adding New Domains
To add a new genomic domain:
- Create domain module:
# gospel/domains/new_domain.py from gospel.core.domain import BaseDomain class NewDomainAnalyzer(BaseDomain): """Analyzer for new genomic domain.""" def analyze_variants(self, variants: List[Variant]) -> DomainResults: """Implement domain-specific analysis.""" pass
- Register domain:
# gospel/domains/__init__.py from .new_domain import NewDomainAnalyzer AVAILABLE_DOMAINS = { 'fitness': FitnessAnalyzer, 'pharmacogenetics': PharmacogeneticsAnalyzer, 'nutrition': NutritionAnalyzer, 'new_domain': NewDomainAnalyzer, # Add here }
- Add tests:
# tests/unit/test_domains/test_new_domain.py class TestNewDomainAnalyzer: def test_analysis(self): # Test implementation pass
- Update documentation:
- Add domain description to
domains.md
- Update CLI help text
- Add examples
- Add domain description to
Adding New Scoring Algorithms
# gospel/core/scoring.py
from abc import ABC, abstractmethod
class VariantScorer(ABC):
"""Base class for variant scoring algorithms."""
@abstractmethod
def score_variant(self, variant: Variant) -> float:
"""Score a genetic variant."""
pass
class CustomScorer(VariantScorer):
"""Custom scoring algorithm."""
def score_variant(self, variant: Variant) -> float:
# Implement custom scoring logic
return score
Adding New Data Sources
# gospel/data/sources.py
class CustomDataSource:
"""Custom genomic data source."""
def fetch_variant_data(self, variant_id: str) -> Dict:
"""Fetch variant data from custom source."""
pass
def get_population_frequencies(self, variant_id: str) -> Dict:
"""Get population frequency data."""
pass
Community
Communication Channels
- GitHub Discussions: General questions and community discussions
- GitHub Issues: Bug reports and feature requests
- Pull Requests: Code contributions and reviews
Code of Conduct
We are committed to providing a welcoming and inclusive environment. Please read our Code of Conduct.
Recognition
Contributors are recognized in:
CONTRIBUTORS.md
file- Release notes
- Documentation acknowledgments
Getting Help
If you need help contributing:
- Check the documentation
- Search existing discussions
- Ask questions in GitHub Discussions
- Join our community calls (announced in discussions)
Thank you for contributing to Gospel! Your contributions help advance the field of genomic analysis and personalized medicine.