Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
177 changes: 177 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
# ET Partition - Continuous Integration / Continuous Deployment
# CI/CD workflow for testing, linting, and quality checks

name: Tests

on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
workflow_dispatch:

# Set minimal permissions for security
permissions:
contents: read

jobs:
# ===================================================================
# Unit Tests
# ===================================================================
test:
name: Python ${{ matrix.python-version }} Tests
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.10", "3.11", "3.12"]

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e .
pip install pytest pytest-cov pytest-timeout

- name: Run unit tests
run: |
pytest tests/ -v --tb=short --timeout=300 --cov=methods --cov=utils --cov-report=xml
timeout-minutes: 10

- name: Upload coverage report
if: matrix.python-version == '3.11'
uses: codecov/codecov-action@v4
with:
files: ./coverage.xml
flags: unittests
fail_ci_if_error: false

# ===================================================================
# Code Quality Checks
# ===================================================================
lint:
name: Code Quality
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
cache: 'pip'

- name: Install linting tools
run: |
python -m pip install --upgrade pip
pip install flake8 mypy

- name: Run flake8
run: |
# Stop the build if there are Python syntax errors or undefined names
flake8 methods/ utils/ --count --select=E9,F63,F7,F82 --show-source --statistics
# Exit-zero treats all errors as warnings
flake8 methods/ utils/ --count --exit-zero --max-complexity=15 --max-line-length=120 --statistics
continue-on-error: true

- name: Run mypy (optional)
run: |
mypy methods/ utils/ --ignore-missing-imports --no-error-summary || true
continue-on-error: true

# ===================================================================
# Integration Tests
# ===================================================================
integration:
name: Integration Tests
runs-on: ubuntu-latest
needs: [test]

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
cache: 'pip'

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e .
pip install pytest pytest-timeout

- name: Run integration tests
run: |
python tests/test_all_methods.py
timeout-minutes: 15
continue-on-error: true

# ===================================================================
# Performance Benchmarks (Optional)
# ===================================================================
benchmark:
name: Performance Benchmarks
runs-on: ubuntu-latest
if: github.event_name == 'push' && github.ref == 'refs/heads/main'

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
cache: 'pip'

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e .

- name: Run benchmarks
run: |
python -c "from utils.benchmark import benchmark_all_methods; benchmark_all_methods(years=1)"
timeout-minutes: 10
continue-on-error: true

# ===================================================================
# Documentation Build (Optional)
# ===================================================================
docs:
name: Documentation
runs-on: ubuntu-latest
if: github.event_name == 'push'

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Verify documentation
run: |
# Check that key documentation files exist
test -f README.md
test -f docs/ET_Partition_Methods_Deep_Dive.md
test -f docs/AI_OPTIMIZATION_PROMPTS.md
test -f notebooks/ET_Partition_Introduction_For_Beginners.ipynb
echo "All documentation files present ✓"

- name: Check markdown links (optional)
run: |
# Basic check for broken internal links
grep -r "\[.*\](\./.*)" docs/ README.md || true
continue-on-error: true
12 changes: 12 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@ __pycache__/
*.dylib
.ipynb_checkpoints/
outputs/

# Test artifacts
.pytest_cache/
*.log
coverage.xml
.coverage
htmlcov/

# IDE
.vscode/
.idea/

# Legacy build artefacts
meta.yaml
build/
Expand Down
52 changes: 46 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,15 +121,30 @@ stored alongside the outputs.

## Tutorials

Three Jupyter notebooks in the `notebooks/` directory mirror the original
method documentation and provide step-by-step demonstrations. Launch them with
JupyterLab after installing the dependencies.
Jupyter notebooks in the `notebooks/` directory provide step-by-step demonstrations:

| Notebook | Description |
|----------|-------------|
| [`ET_Partition_Introduction_For_Beginners.ipynb`](notebooks/ET_Partition_Introduction_For_Beginners.ipynb) | **New!** Comprehensive beginner's guide (bilingual EN/CN) |
| [`Zhou_tutorial.ipynb`](notebooks/Zhou_tutorial.ipynb) | uWUE method tutorial |
| [`TEA_tutorial.ipynb`](notebooks/TEA_tutorial.ipynb) | TEA method tutorial |
| [`Perez-Priego_tutorial.ipynb`](notebooks/Perez-Priego_tutorial.ipynb) | Perez-Priego method tutorial |

Launch them with JupyterLab after installing the dependencies:

```bash
pip install jupyterlab
jupyter lab
```

## Documentation

| Document | Description |
|----------|-------------|
| [`docs/ET_Partition_Methods_Deep_Dive.md`](docs/ET_Partition_Methods_Deep_Dive.md) | **New!** In-depth technical documentation with mathematical derivations |
| [`docs/partition_methods_math.md`](docs/partition_methods_math.md) | Original mathematical foundations |
| [`docs/AI_OPTIMIZATION_PROMPTS.md`](docs/AI_OPTIMIZATION_PROMPTS.md) | **New!** AI coding assistant prompts for development |

## Third-party material

The `third_party/` directory contains unmodified resources from the original
Expand All @@ -138,13 +153,38 @@ are preserved for traceability but are not imported by default.

## Testing

A comprehensive test script is provided to validate all methods using the sample data:
A comprehensive test suite validates all methods using the sample data:

```bash
python tests/test_all_methods.py
# Run all tests with pytest
pytest tests/ -v

# Run specific test categories
pytest tests/test_all_methods.py -v # Integration tests
pytest tests/test_complex_scenarios.py -v # Edge cases and benchmarks

# Run with coverage
pytest tests/ --cov=methods --cov=utils
```

This will run all three methods on the FI-Hyy test site and verify the outputs.
The test suite includes:
- **Integration tests**: Full workflow validation for all three methods
- **Complex scenarios**: Missing data handling, multi-biome scenarios
- **Performance benchmarks**: Execution time and memory tests
- **Edge cases**: Zero GPP, extreme VPD, negative fluxes

## Performance Optimization

The codebase includes optimized implementations for better performance:

- **Numba-accelerated Perez-Priego**: 5-10x speedup (`methods/perez_priego/et_partitioning_functions_numba.py`)
- **Vectorized uWUE**: Fully vectorized operations (`methods/uwue/zhou_optimized.py`)
- **Benchmark utilities**: Performance profiling tools (`utils/benchmark.py`)

Run benchmarks:
```bash
python -m utils.benchmark --years 3
```

## Method descriptions

Expand Down
Loading
Loading