Contributing to SNID SAGE¶
Thank you for your interest in contributing to SNID SAGE! This guide will help you get started with development and contributions.
Ways to Contribute¶
For Everyone¶
- Report bugs and issues
- Suggest new features
- Improve documentation
- Test with different data
- Share analysis results
For Developers¶
- Fix bugs and issues
- Implement new features
- Performance improvements
- Add test coverage
- Code refactoring
For Scientists¶
- Contribute templates
- Scientific validation
- Publications and citations
- Educational content
- Feature requests from research
Getting Started¶
Development Setup¶
1. Fork and Clone¶
# Fork the repository on GitHub
# Then clone your fork
git clone https://github.com/yourusername/SNID_SAGE.git
cd SNID_SAGE
# Add upstream remote
git remote add upstream https://github.com/FiorenSt/SNID-SAGE.git
2. Set Up Development Environment¶
# Create virtual environment
python -m venv venv_dev
source venv_dev/bin/activate # Linux/macOS
# or venv_dev\Scripts\activate # Windows
# Install in development mode
pip install -e .
pip install -r requirements-dev.txt
3. Verify Installation¶
Development Dependencies¶
# requirements-dev.txt (additional development tools)
pytest>=7.0.0
pytest-cov>=4.0.0
black>=22.0.0
flake8>=5.0.0
mypy>=1.0.0
sphinx>=5.0.0
pre-commit>=2.20.0
Development Workflow¶
1. Create Feature Branch¶
# Update your fork
git fetch upstream
git checkout main
git merge upstream/main
# Create feature branch
git checkout -b feature/your-feature-name
2. Make Changes¶
- Follow coding standards
- Add tests for new features
- Update documentation
- Test thoroughly
3. Commit and Push¶
# Stage changes
git add .
# Commit with descriptive message
git commit -m "Add: New feature description
- Detailed description of changes
- Any breaking changes noted
- References to issues if applicable"
# Push to your fork
git push origin feature/your-feature-name
4. Create Pull Request¶
- Use clear title and description
- Reference related issues
- Include screenshots for UI changes
- Add tests and documentation
Code Style Guide¶
Python Style¶
Follow PEP 8 with modifications:¶
- Line length: 100 characters (not 79)
- Use
black
for automatic formatting - Use
flake8
for linting
Formatting¶
# Auto-format code
black snid_sage/ interfaces/ shared/ tests/
# Check style
flake8 snid_sage/ interfaces/ shared/ tests/
# Type checking
mypy snid_sage/ interfaces/ shared/
Naming Conventions¶
# Classes: PascalCase
class SpectrumAnalyzer:
pass
# Functions/variables: snake_case
def analyze_spectrum(wavelength_data):
pass
# Constants: UPPER_SNAKE_CASE
SPEED_OF_LIGHT = 299792458
# Private methods: _leading_underscore
def _internal_method(self):
pass
Documentation Style¶
Docstrings (Google Style)¶
def analyze_spectrum(wavelength: np.ndarray, flux: np.ndarray) -> AnalysisResult:
"""Analyze a supernova spectrum using template matching.
Args:
wavelength: Wavelength array in Angstroms
flux: Flux array in arbitrary units
Returns:
AnalysisResult containing classification and parameters
Raises:
ValueError: If wavelength and flux arrays have different lengths
AnalysisError: If analysis fails due to poor data quality
Example:
>>> result = analyze_spectrum(wavelength, flux)
>>> print(f"Type: {result.type}, Confidence: {result.confidence}")
"""
Comments¶
# Use inline comments sparingly, prefer clear variable names
correlation_coefficient = 0.87 # Good match threshold
# Use block comments for complex algorithms
# Cross-correlation using FFT for efficiency:
# 1. Zero-pad both arrays to same length
# 2. Compute FFT of both arrays
# 3. Multiply FFT(a) * conj(FFT(b))
# 4. Inverse FFT to get correlation
Project Architecture¶
Directory Structure¶
SNID_SAGE/
├── snid_sage/ # Core algorithm
├── interfaces/ # User interfaces
│ ├── cli/ # Command-line interface
│ ├── gui/ # Graphical interface
│ └── llm/ # AI integration
├── shared/ # Shared utilities
│ ├── constants/ # Physical constants
│ ├── exceptions/ # Custom exceptions
│ ├── types/ # Type definitions
│ └── utils/ # Utility functions
├── tests/ # Test suite
├── docs/ # Documentation
└── scripts/ # Utility scripts
Design Principles¶
1. Separation of Concerns¶
- Core algorithm independent of interfaces
- GUI/CLI as thin wrappers around core
- AI integration as optional enhancement
2. Type Safety¶
from typing import Optional, List, Tuple
from shared.types import SpectrumData, AnalysisResult
def analyze(spectrum: SpectrumData,
templates: List[SpectrumData]) -> AnalysisResult:
"""Type-safe analysis function."""
3. Error Handling¶
from shared.exceptions import SpectrumLoadError, AnalysisError
try:
spectrum = load_spectrum(filename)
except SpectrumLoadError as e:
logger.error(f"Failed to load {filename}: {e}")
raise
4. Configuration Management¶
from shared.utils.config import get_config
config = get_config()
correlation_method = config.analysis.correlation_method
Testing Guidelines¶
Test Structure¶
tests/
├── unit/ # Unit tests
│ ├── test_snid_core.py # Core algorithm tests
│ ├── test_preprocessing.py
│ └── test_io.py
├── integration/ # Integration tests
│ ├── test_cli.py # CLI functionality
│ └── test_gui.py # GUI functionality
├── fixtures/ # Test data
│ ├── spectra/ # Sample spectra
│ └── templates/ # Test templates
└── conftest.py # Pytest configuration
Writing Tests¶
Unit Tests¶
import pytest
import numpy as np
from snid_sage.snid.preprocessing import normalize_spectrum
def test_normalize_spectrum():
"""Test spectrum normalization."""
# Arrange
wavelength = np.linspace(4000, 7000, 100)
flux = np.random.normal(1.0, 0.1, 100)
# Act
normalized_flux = normalize_spectrum(wavelength, flux)
# Assert
assert np.isclose(np.median(normalized_flux), 1.0, rtol=0.1)
assert len(normalized_flux) == len(flux)
assert not np.any(np.isnan(normalized_flux))
def test_normalize_spectrum_empty():
"""Test normalization with empty input."""
with pytest.raises(ValueError, match="Empty spectrum"):
normalize_spectrum(np.array([]), np.array([]))
Integration Tests¶
def test_cli_identify_command(tmpdir):
"""Test CLI identify command end-to-end."""
import subprocess
# Create test spectrum
test_spectrum = tmpdir.join("test_spectrum.dat")
test_spectrum.write("4000 1.0\n4001 1.1\n4002 0.9\n")
# Run CLI command
result = subprocess.run([
"python", "run_snid_cli.py", "identify", str(test_spectrum)
], capture_output=True, text=True)
# Check results
assert result.returncode == 0
assert "Type:" in result.stdout
Running Tests¶
# Run all tests
pytest
# Run with coverage
pytest --cov=snid_sage --cov=interfaces --cov=shared
# Run specific test file
pytest tests/unit/test_snid_sage_core.py -v
# Run tests matching pattern
pytest -k "test_normalize" -v
Documentation Guidelines¶
Types of Documentation¶
1. Code Documentation¶
- Docstrings for all public functions/classes
- Type hints for function signatures
- Inline comments for complex logic
2. User Documentation¶
- Installation guides
- Tutorials and examples
- API reference
- FAQ and troubleshooting
3. Developer Documentation¶
- Architecture overview
- Contributing guidelines
- Release notes
- Development setup
Documentation Tools¶
Markdown for Guides¶
# Use clear headings
## Subsections help navigation
### Examples with code blocks
```python
# Code examples should be runnable
result = analyze_spectrum(wavelength, flux)
Bold for emphasis, italic for variables.
#### **Sphinx for API Documentation**
```python
# Install Sphinx
pip install sphinx sphinx-autodoc-typehints
# Generate documentation
cd docs/
make html
Bug Reports¶
Before Reporting¶
- Check existing issues
- Try latest version
- Verify it's reproducible
- Check documentation
Good Bug Report Template¶
## Bug Description
Clear description of what went wrong.
## Steps to Reproduce
1. Load spectrum file `example.dat`
2. Run analysis with default parameters
3. Click "Export Results"
4. Error occurs
## Expected Behavior
Results should export to JSON file.
## Actual Behavior
Error message: "Unable to write file"
## Environment
- OS: Windows 10
- Python: 3.9.7
- SNID SAGE: v2.0.1
- Error log: [attach log file]
## Additional Context
- File permissions are correct
- Disk space available
- Works with other spectra
Feature Requests¶
Good Feature Request Template¶
## Feature Description
Add support for multi-object spectra analysis.
## Use Case
When analyzing fiber spectra from SDSS, need to process
multiple objects simultaneously.
## Proposed Solution
Add batch processing mode that:
1. Reads multi-extension FITS files
2. Processes each spectrum independently
3. Generates combined results report
## Alternatives Considered
- Manual processing (too slow)
- External scripts (complex)
## Additional Context
Would benefit astronomical surveys and large datasets.
Release Process¶
Version Numbering¶
- Major (X.0.0): Breaking changes
- Minor (0.X.0): New features, backward compatible
- Patch (0.0.X): Bug fixes only
Release Checklist¶
- All tests pass
- Documentation updated
- Version numbers updated
- Changelog updated
- Create GitHub release
- Update package registries
Community Guidelines¶
Code of Conduct¶
- Be respectful and inclusive
- Focus on technical merit
- Help newcomers learn
- Credit contributors appropriately
Communication Channels¶
- GitHub Issues: Bug reports, feature requests
- GitHub Discussions: Questions, ideas, help
- Pull Requests: Code contributions
- Email: Sensitive security issues
Recognition¶
Contributors are acknowledged in: - README contributors section - Release notes - Academic publications (for significant contributions) - Conference presentations
Contribution Examples¶
Beginner-Friendly¶
- Fix typos in documentation
- Add example spectrum files
- Improve error messages
- Add unit tests for existing functions
Intermediate¶
- Implement new preprocessing options
- Add support for new file formats
- Improve GUI usability
- Optimize performance bottlenecks
Advanced¶
- Add new correlation algorithms
- Implement machine learning features
- Extend AI integration capabilities
- Add support for new instrument types
Getting Help¶
Development Questions¶
- Check existing documentation
- Search GitHub issues/discussions
- Ask specific, focused questions
- Provide context and examples
Mentorship¶
New contributors can request mentorship for: - Understanding codebase - Choosing appropriate issues - Code review feedback - Best practices guidance
Ready to contribute? Check out our good first issues or reach out on GitHub Discussions!