Skip to content

Navigation Menu

Sign in
Sign up

Development Setup

github-actions[bot] edited this page Nov 15, 2025 · 2 revisions

Development Setup

Complete guide to setting up a development environment for contributing to DVOACAP-Python.

Table of Contents


Prerequisites

Required Software

Python 3.8 or higher:

# Check your Python version
python3 --version
# Should output: Python 3.8.0 or higher

Git:

# Install git (if not already installed)
# Ubuntu/Debian
sudo apt-get install git
# macOS
brew install git
# Windows
# Download from https://git-scm.com/download/win

pip and virtualenv:

# Install pip (usually included with Python)
python3 -m ensurepip --upgrade
# Install virtualenv
pip install virtualenv

Getting Started

1. Fork and Clone Repository

Fork the repository on GitHub:

Clone your fork:

git clone https://github.com/YOUR_USERNAME/dvoacap-python.git
cd dvoacap-python

Add upstream remote:

git remote add upstream https://github.com/skyelaird/dvoacap-python.git
git fetch upstream

2. Create Virtual Environment

Create and activate virtual environment:

# Create virtual environment
python3 -m venv venv
# Activate (Linux/macOS)
source venv/bin/activate
# Activate (Windows)
venv\Scripts\activate
# Your prompt should change to show (venv)

3. Install in Development Mode

Install DVOACAP with all development dependencies:

# Install in editable mode with all extras
pip install -e ".[all]"
# This installs:
# - dvoacap library (core)
# - dashboard dependencies (flask, etc.)
# - dev tools (pytest, black, flake8, mypy)
# - documentation tools (sphinx, sphinx-rtd-theme)

Verify installation:

# Test import
python3 -c "import dvoacap; print(dvoacap.__version__)"
# Should output: 0.5.0
# Run a quick test
pytest tests/test_path_geometry.py -v

4. Configure Development Tools

Install pre-commit hooks (optional but recommended):

# Install pre-commit
pip install pre-commit
# Set up git hooks
pre-commit install
# Run against all files to test
pre-commit run --all-files

Development Tools

Code Formatting: Black

DVOACAP-Python uses Black for consistent code formatting.

Configuration (from pyproject.toml):

[tool.black]
line-length = 100
target-version = ['py38', 'py39', 'py310', 'py311', 'py312']

Usage:

# Format a single file
black src/dvoacap/path_geometry.py
# Format all Python files
black src/ tests/ examples/
# Check without modifying
black --check src/

Linting: Flake8

Use Flake8 for code quality checks.

Usage:

# Lint a file
flake8 src/dvoacap/path_geometry.py
# Lint entire project
flake8 src/ tests/
# Configuration in setup.cfg or pyproject.toml

Common issues:

  • Line too long (E501) - Black should handle this
  • Unused imports (F401) - Remove unused imports
  • Undefined name (F821) - Check for typos

Type Checking: mypy

Use mypy for optional static type checking.

Configuration (from pyproject.toml):

[tool.mypy]
python_version = "3.8"
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = false

Usage:

# Check a file
mypy src/dvoacap/path_geometry.py
# Check entire package
mypy src/dvoacap/
# Ignore errors for now (many modules not fully typed)
mypy --ignore-missing-imports src/

Testing: pytest

Run tests with pytest.

Usage:

# Run all tests
pytest
# Run with verbose output
pytest -v
# Run specific test file
pytest tests/test_path_geometry.py
# Run specific test function
pytest tests/test_path_geometry.py::test_distance_calculation
# Run with coverage
pytest --cov=dvoacap tests/
# Generate HTML coverage report
pytest --cov=dvoacap --cov-report=html tests/
# Open htmlcov/index.html in browser

Configuration (from pyproject.toml):

[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
addopts = "-v --tb=short"

Project Structure

dvoacap-python/
├── src/
│ └── dvoacap/ # Main Python package
│ ├── __init__.py # Package initialization
│ ├── path_geometry.py # Phase 1: Path geometry
│ ├── solar.py # Phase 2: Solar calculations
│ ├── geomagnetic.py # Phase 2: Geomagnetic field
│ ├── fourier_maps.py # Phase 3: CCIR/URSI maps
│ ├── ionospheric_profile.py # Phase 3: Ionosphere modeling
│ ├── layer_parameters.py # Phase 3: Layer parameters
│ ├── muf_calculator.py # Phase 4: MUF calculations
│ ├── reflectrix.py # Phase 4: Raytracing
│ ├── prediction_engine.py # Phase 5: Prediction engine
│ ├── noise_model.py # Phase 5: Noise modeling
│ └── antenna_gain.py # Phase 5: Antenna calculations
│
├── tests/ # Test suite
│ ├── test_path_geometry.py # Path geometry tests
│ ├── test_ionospheric.py # Ionospheric tests
│ └── test_voacap_parser.py # VOACAP reference tests
│
├── examples/ # Usage examples
│ ├── complete_prediction_example.py
│ ├── phase4_raytracing_example.py
│ └── integration_example.py
│
├── Dashboard/ # Web dashboard
│ ├── dashboard.html # Main UI
│ ├── server.py # Flask server
│ ├── generate_predictions.py # Prediction generator
│ └── README.md # Dashboard docs
│
├── DVoaData/ # CCIR/URSI coefficient data
│ ├── ccir*.asc # CCIR coefficients
│ └── ursi*.asc # URSI coefficients
│
├── SampleIO/ # Sample input/output files
│ └── voacap_reference/ # Reference VOACAP output
│
├── docs/ # Documentation
│ ├── source/ # Sphinx source
│ ├── build/ # Built documentation
│ └── *.md, *.pdf # Various docs
│
├── wiki/ # GitHub wiki (this documentation)
│ ├── Home.md
│ ├── Getting-Started.md
│ └── ...
│
├── pyproject.toml # Package configuration
├── README.md # Main README
├── LICENSE # MIT License
└── .gitignore # Git ignore rules

Code Style

General Conventions

Follow PEP 8 with these specifics:

  • Line length: 100 characters (Black default)
  • Indentation: 4 spaces (no tabs)
  • Imports: Grouped (standard library, third-party, local)
  • Naming:
    • Functions/variables: snake_case
    • Classes: PascalCase
    • Constants: UPPER_CASE

Example:

"""Module docstring explaining purpose."""
import math
from typing import List, Tuple
import numpy as np
from dvoacap.path_geometry import GeoPoint
class PredictionEngine:
 """Class docstring explaining the class."""
 MAX_FREQUENCY = 30.0 # Constant
 def __init__(self, location: GeoPoint):
 """Initialize prediction engine."""
 self.location = location
 self._cache = {} # Private attribute
 def predict(self, frequencies: List[float]) -> np.ndarray:
 """
 Run propagation prediction.

 Args:
 frequencies: List of frequencies in MHz

 Returns:
 Array of predictions
 """
 # Implementation
 pass

Docstrings

Use NumPy/Google style docstrings:

def calculate_muf(foF2: float, hop_count: int, elevation: float) -> float:
 """
 Calculate Maximum Usable Frequency.

 Args:
 foF2: F2 layer critical frequency in MHz
 hop_count: Number of hops (1-4)
 elevation: Elevation angle in radians

 Returns:
 MUF in MHz

 Raises:
 ValueError: If hop_count < 1

 Example:
 >>> calculate_muf(foF2=8.5, hop_count=2, elevation=0.1)
 15.2
 """
 if hop_count < 1:
 raise ValueError("hop_count must be >= 1")
 # Implementation
 return foF2 * 3.14 / math.sin(elevation)

Type Hints

Use type hints for function signatures:

from typing import List, Tuple, Optional
import numpy as np
def process_frequencies(
 frequencies: List[float],
 ssn: float,
 month: int
) -> Tuple[np.ndarray, Optional[str]]:
 """Process frequencies and return results."""
 # Implementation
 pass

Testing

Writing Tests

Test file structure:

# tests/test_my_module.py
import pytest
import numpy as np
from dvoacap.my_module import MyClass
class TestMyClass:
 """Tests for MyClass"""
 def test_basic_functionality(self):
 """Test basic usage"""
 obj = MyClass()
 result = obj.method(42)
 assert result == 84
 def test_edge_case(self):
 """Test edge case"""
 obj = MyClass()
 with pytest.raises(ValueError):
 obj.method(-1)
 @pytest.mark.parametrize("input,expected", [
 (1, 2),
 (2, 4),
 (3, 6),
 ])
 def test_multiple_values(self, input, expected):
 """Test multiple input values"""
 obj = MyClass()
 assert obj.method(input) == expected

Run tests:

# All tests
pytest
# Specific module tests
pytest tests/test_path_geometry.py
# With coverage
pytest --cov=dvoacap --cov-report=term-missing

Validation Tests

Run VOACAP reference validation:

# Full validation suite
python3 test_voacap_reference.py
# Specific phase validation
pytest tests/test_ionospheric.py -v

See Testing Guide for detailed testing instructions.


Documentation

Building Sphinx Documentation

Install Sphinx dependencies:

pip install -e ".[docs]"

Build HTML documentation:

Linux/macOS:

cd docs
make html

Windows:

cd docs
.\make.bat html
# Or use PowerShell script
.\make.ps1 html
# Or direct sphinx-build
sphinx-build -M html source build

View documentation:

# Open in browser
open docs/build/html/index.html # macOS
xdg-open docs/build/html/index.html # Linux
start docs/build/html/index.html # Windows

Contributing to Wiki

Wiki pages are in the /wiki directory:

# Edit a wiki page
vi wiki/Development-Setup.md
# Add new page
vi wiki/New-Page.md
# Commit and push
git add wiki/
git commit -m "Update wiki documentation"
git push origin main

Git Workflow

Branch Strategy

Main branches:

  • main - Stable releases
  • Feature branches - Development work

Create feature branch:

# Update main
git checkout main
git pull upstream main
# Create feature branch
git checkout -b feature/my-feature
# Work on your changes
# ...
# Commit regularly
git add .
git commit -m "Add feature description"

Making Changes

1. Make changes:

# Edit files
vi src/dvoacap/my_module.py
# Format code
black src/dvoacap/my_module.py
# Run tests
pytest tests/test_my_module.py

2. Commit changes:

# Stage changes
git add src/dvoacap/my_module.py tests/test_my_module.py
# Commit with clear message
git commit -m "Add new feature: detailed description"

3. Push to your fork:

git push origin feature/my-feature

4. Create Pull Request:

  • Visit your fork on GitHub
  • Click "New Pull Request"
  • Fill in description
  • Submit for review

Keeping Your Fork Updated

# Fetch upstream changes
git fetch upstream
# Update main
git checkout main
git merge upstream/main
# Rebase feature branch (if needed)
git checkout feature/my-feature
git rebase main
# Resolve any conflicts, then:
git push --force-with-lease origin feature/my-feature

Development Workflow Example

Complete workflow for adding a new feature:

# 1. Set up environment
git clone https://github.com/YOUR_USERNAME/dvoacap-python.git
cd dvoacap-python
python3 -m venv venv
source venv/bin/activate
pip install -e ".[all]"
# 2. Create feature branch
git checkout -b feature/add-new-feature
# 3. Make changes
# Edit source files
vi src/dvoacap/new_module.py
# 4. Write tests
vi tests/test_new_module.py
# 5. Format and lint
black src/ tests/
flake8 src/ tests/
# 6. Run tests
pytest tests/test_new_module.py -v
# 7. Update documentation
vi docs/source/api/new_module.rst
# 8. Commit changes
git add src/dvoacap/new_module.py tests/test_new_module.py docs/
git commit -m "Add new module for feature X"
# 9. Push and create PR
git push origin feature/add-new-feature
# Create pull request on GitHub

Next Steps


Troubleshooting Development Setup

"ModuleNotFoundError: No module named 'dvoacap'"

Solution:

# Ensure installed in editable mode
pip install -e .

"pytest: command not found"

Solution:

# Install dev dependencies
pip install -e ".[dev]"

Black formatting conflicts

Solution:

# Use Black's configuration
black --line-length=100 src/

Import errors in tests

Solution:

# Ensure virtual environment is activated
source venv/bin/activate
# Reinstall package
pip install -e .

Ready to contribute? Check out the Contributing Guide for detailed contribution guidelines!

Clone this wiki locally

AltStyle によって変換されたページ (->オリジナル) /