Contributing to InSARLiteο
Thank you for your interest in contributing to InSARLite! This guide will help you get started with contributing to the project.
Ways to Contributeο
π Bug Reportsο
Help us improve InSARLite by reporting bugs:
Use GitHub Issues with the bug report template
Include detailed steps to reproduce the issue
Provide system information and error logs
Test with the latest version before reporting
π‘ Feature Requestsο
Suggest new features or improvements:
Use GitHub Issues with the feature request template
Describe the use case and expected behavior
Consider implementation complexity and scope
Discuss with the community before large changes
π Documentationο
Improve documentation:
Fix typos and grammatical errors
Add missing documentation
Create tutorials and examples
Translate documentation to other languages
π» Code Contributionsο
Contribute code improvements:
Bug fixes and stability improvements
New features and functionality
Performance optimizations
Test coverage improvements
π§ͺ Testingο
Help improve software quality:
Write and improve unit tests
Test new features and bug fixes
Report edge cases and corner bugs
Validate cross-platform compatibility
π¬ Community Supportο
Help other users:
Answer questions in GitHub Discussions
Help troubleshoot issues
Share usage examples and tips
Mentor new contributors
Getting Startedο
Development Environment Setupο
Fork the Repository
# Fork on GitHub, then clone your fork git clone https://github.com/yourusername/InSARLite.git cd InSARLite
Set Up Development Environment
# Create virtual environment python -m venv venv source venv/bin/activate # Linux/macOS # or venv\Scripts\activate # Windows # Install development dependencies pip install -e .[dev]
Install Development Tools
# Install pre-commit hooks pre-commit install # Install testing tools pip install pytest pytest-cov black flake8 mypy
Verify Installation
# Run tests to ensure everything works python -m pytest tests/ # Start the application python -m insarlite.main
Development Workflowο
Create Feature Branch
git checkout -b feature/your-feature-name
Make Changes
Follow coding standards (see below)
Add tests for new functionality
Update documentation as needed
Test Your Changes
# Run full test suite python -m pytest tests/ -v # Check code style black --check src/ flake8 src/ # Type checking mypy src/
Commit Changes
git add . git commit -m "feat: add new feature description"
Push and Create Pull Request
git push origin feature/your-feature-name
Then create a Pull Request on GitHub.
Coding Standardsο
Python Style Guideο
We follow PEP 8 with some specific guidelines:
Code Formatting:
# Use Black for automatic formatting
black src/ tests/
# Line length: 88 characters (Black default)
# Use double quotes for strings
# 4 spaces for indentation
Import Organization:
# Standard library imports
import os
import sys
from pathlib import Path
# Third-party imports
import numpy as np
import matplotlib.pyplot as plt
import tkinter as tk
# Local imports
from .utils import helper_function
from ..gmtsar_gui import processing_module
Naming Conventions:
# Variables and functions: snake_case
variable_name = "value"
def function_name():
pass
# Classes: PascalCase
class ClassName:
pass
# Constants: UPPER_CASE
MAX_RETRIES = 3
# Private members: _leading_underscore
def _private_function():
pass
Documentation Standardsο
Docstring Format (Google Style):
def process_data(input_path: Path, options: Dict[str, Any]) -> List[str]:
"""
Process InSAR data from input directory.
This function processes Sentinel-1 data according to the specified
options and returns a list of output file paths.
Args:
input_path: Path to directory containing input data files.
options: Dictionary containing processing options. Must include
'output_dir' key and optionally 'parallel_workers'.
Returns:
List of paths to generated output files.
Raises:
ValueError: If input_path does not exist or is not a directory.
ProcessingError: If processing fails due to data issues.
Example:
>>> from pathlib import Path
>>> result = process_data(Path("data/"), {"output_dir": "results/"})
>>> print(len(result))
5
"""
pass
Type Hints:
from typing import List, Dict, Optional, Union, Tuple
from pathlib import Path
def analyze_baselines(
acquisitions: List[Dict[str, str]],
max_temporal: int = 48,
max_perpendicular: Optional[float] = None
) -> Tuple[List[Tuple[str, str]], Dict[str, float]]:
"""Analyze baseline network and return optimal pairs."""
pass
GUI Development Guidelinesο
Tkinter Best Practices:
class MyDialog(tk.Toplevel):
"""Example dialog following InSARLite patterns."""
def __init__(self, parent: tk.Widget, title: str):
super().__init__(parent)
self.title(title)
self.transient(parent)
self.grab_set()
self._create_widgets()
self._bind_events()
# Center on parent
self.geometry("+%d+%d" % (
parent.winfo_rootx() + 50,
parent.winfo_rooty() + 50
))
def _create_widgets(self):
"""Create and layout widgets."""
# Implementation here
pass
def _bind_events(self):
"""Bind event handlers."""
# Implementation here
pass
Threading for GUI:
import threading
from concurrent.futures import ThreadPoolExecutor
class ProcessingDialog(tk.Toplevel):
def __init__(self, parent):
super().__init__(parent)
self.executor = ThreadPoolExecutor(max_workers=1)
def start_processing(self):
"""Start processing in background thread."""
future = self.executor.submit(self._process_data)
self._check_processing_complete(future)
def _process_data(self):
"""Background processing function."""
# Long-running operation
return result
def _check_processing_complete(self, future):
"""Check if background processing is complete."""
if future.done():
try:
result = future.result()
self._on_processing_complete(result)
except Exception as e:
self._on_processing_error(e)
else:
# Check again in 100ms
self.after(100, lambda: self._check_processing_complete(future))
Testing Guidelinesο
Test Organizationο
tests/
βββ unit/ # Unit tests
β βββ test_utils.py
β βββ test_config.py
β βββ test_processing.py
βββ integration/ # Integration tests
β βββ test_download.py
β βββ test_workflow.py
βββ gui/ # GUI tests
β βββ test_main_window.py
β βββ test_dialogs.py
βββ fixtures/ # Test data and fixtures
βββ sample_data/
βββ mock_responses/
Writing Testsο
Unit Test Example:
import unittest
from unittest.mock import Mock, patch, MagicMock
from pathlib import Path
from insarlite.utils.config_manager import ConfigManager
class TestConfigManager(unittest.TestCase):
"""Test cases for ConfigManager class."""
def setUp(self):
"""Set up test fixtures."""
self.config_manager = ConfigManager()
self.test_config = {
"data_folder": "/path/to/data",
"output_folder": "/path/to/output"
}
def test_load_default_config(self):
"""Test loading default configuration."""
config = self.config_manager.load_default_config()
self.assertIsInstance(config, dict)
self.assertIn("data_folder", config)
@patch('pathlib.Path.exists')
@patch('json.load')
def test_load_config_file_exists(self, mock_json_load, mock_exists):
"""Test loading configuration from existing file."""
mock_exists.return_value = True
mock_json_load.return_value = self.test_config
with patch('builtins.open', mock_open()):
config = self.config_manager.load_config()
self.assertEqual(config, self.test_config)
mock_json_load.assert_called_once()
def test_validate_config_valid(self):
"""Test validation of valid configuration."""
is_valid = self.config_manager.validate_config(self.test_config)
self.assertTrue(is_valid)
def test_validate_config_missing_key(self):
"""Test validation fails for missing required key."""
invalid_config = {"data_folder": "/path/to/data"}
is_valid = self.config_manager.validate_config(invalid_config)
self.assertFalse(is_valid)
Integration Test Example:
import unittest
import tempfile
import shutil
from pathlib import Path
from insarlite.gmtsar_gui.data_dwn import DataDownloader
class TestDataDownloadIntegration(unittest.TestCase):
"""Integration tests for data download functionality."""
def setUp(self):
"""Set up test environment."""
self.temp_dir = Path(tempfile.mkdtemp())
self.downloader = DataDownloader()
def tearDown(self):
"""Clean up test environment."""
shutil.rmtree(self.temp_dir)
@unittest.skipIf(not has_internet(), "Requires internet connection")
def test_search_and_download_integration(self):
"""Test complete search and download workflow."""
# Search for data
results = self.downloader.search_acquisitions(
start_date="2023-01-01",
end_date="2023-01-07",
aoi_wkt="POLYGON((-118.5 34.0, -118.2 34.0, -118.2 34.2, -118.5 34.2, -118.5 34.0))"
)
self.assertGreater(len(results), 0)
# Download first result (if available)
if results:
download_success = self.downloader.download_acquisition(
results[0], self.temp_dir
)
self.assertTrue(download_success)
Test Data and Fixturesο
Creating Test Fixtures:
import pytest
from pathlib import Path
@pytest.fixture
def sample_safe_directory():
"""Create a mock Sentinel-1 SAFE directory structure."""
temp_dir = Path(tempfile.mkdtemp())
safe_dir = temp_dir / "S1A_IW_SLC__1SDV_20230101T120000_20230101T120027_046123_058456_1234.SAFE"
safe_dir.mkdir()
# Create mock files
(safe_dir / "manifest.safe").write_text("mock manifest")
(safe_dir / "annotation").mkdir()
(safe_dir / "measurement").mkdir()
yield safe_dir
# Cleanup
shutil.rmtree(temp_dir)
def test_safe_directory_parsing(sample_safe_directory):
"""Test parsing of SAFE directory structure."""
from insarlite.utils.utils import parse_safe_directory
metadata = parse_safe_directory(sample_safe_directory)
assert metadata is not None
assert "acquisition_date" in metadata
Pull Request Processο
Before Submittingο
Run Full Test Suite
python -m pytest tests/ -v --cov=src/insarlite
Check Code Quality
# Format code black src/ tests/ # Check style flake8 src/ tests/ # Type checking mypy src/
Update Documentation
Add docstrings for new functions/classes
Update user documentation if needed
Add examples for new features
Add Tests
Unit tests for new functions
Integration tests for new workflows
GUI tests for interface changes
Pull Request Templateο
When creating a pull request, please include:
## Description
Brief description of changes and motivation.
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Documentation update
- [ ] Performance improvement
- [ ] Code refactoring
## Testing
- [ ] Unit tests pass
- [ ] Integration tests pass
- [ ] Manual testing completed
- [ ] New tests added
## Documentation
- [ ] Docstrings updated
- [ ] User documentation updated
- [ ] API documentation updated
## Checklist
- [ ] Code follows style guidelines
- [ ] Self-review completed
- [ ] Comments added for complex logic
- [ ] No new warnings introduced
Review Processο
Automated Checks: CI/CD pipeline runs automatically
Code Review: Maintainers review code quality and design
Testing: Verify functionality and test coverage
Documentation: Check documentation completeness
Approval: At least one maintainer approval required
Community Guidelinesο
Code of Conductο
We are committed to providing a welcoming and inclusive environment:
Be Respectful: Treat all community members with respect
Be Inclusive: Welcome contributors from all backgrounds
Be Constructive: Provide helpful and constructive feedback
Be Patient: Help newcomers learn and contribute
Communicationο
GitHub Issues: For bug reports and feature requests
GitHub Discussions: For questions and general discussion
Pull Request Comments: For code-specific discussions
Email: For private matters or security issues
Recognitionο
We recognize contributors through:
Contributors List: Listed in repository and documentation
Release Notes: Acknowledgment in release announcements
Community Highlights: Featured contributions in updates
Getting Helpο
For Contributorsο
Documentation: This contributing guide and developer docs
Examples: Look at existing code for patterns and conventions
Ask Questions: Use GitHub Discussions for help
Mentorship: Request guidance from experienced contributors
For Maintainersο
Review Guidelines: Standards for code review
Release Process: Steps for creating releases
Issue Triage: Guidelines for managing issues
Community Management: Practices for community interaction
Resourcesο
Development Toolsο
IDEs: VS Code, PyCharm, or your preferred editor
Version Control: Git with GitHub
Testing: pytest for test execution
Documentation: Sphinx for documentation generation
CI/CD: GitHub Actions for automated testing
Learning Resourcesο
Python: Official Python Tutorial
Tkinter: Tkinter Documentation
Testing: pytest Documentation
InSAR: Background on InSAR processing concepts
Thank you for contributing to InSARLite! Your contributions help make InSAR processing more accessible to everyone. π