- Python 92.3%
- Makefile 7.7%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
|
||
| data | ||
| examples | ||
| src/sopra | ||
| tests | ||
| .gitignore | ||
| LICENSE | ||
| Makefile | ||
| MANIFEST.in | ||
| PACKAGE_SUMMARY.md | ||
| publiccode.yml | ||
| pyproject.toml | ||
| README.md | ||
| requirements-demo.txt | ||
| requirements.txt | ||
| RESTRUCTURING.md | ||
| verify_package.py | ||
SOPRA Python Package
🎯 Overview
This package contains a complete, standalone Python implementation of the SOPRA model for Grapholita funebrana (plum fruit moth) population dynamics. The implementation has been translated from the original Pascal version and thoroughly validated against Pascal reference results.
📦 Installation
From Source (Recommended for Development)
# Clone or download this repository
cd SOPRA_Python_Standalone
# Install in development mode with all dependencies
pip install -e .[all]
# Or install with specific optional dependencies
pip install -e .[jupyter] # For Jupyter notebook support
pip install -e .[dev] # For development tools
Basic Installation
# Install only core dependencies
pip install -e .
Requirements
- Python 3.8+
- numpy >= 1.21.0
- pandas >= 1.3.0
- matplotlib >= 3.4.0
Optional dependencies:
- jupyter >= 1.0.0 (for notebook examples)
- networkx >= 2.6.0 (for visualization)
📦 Package Structure
graphoPy/
├── src/sopra/ # Main package directory
│ ├── __init__.py # Package initialization and exports
│ ├── core.py # Core SOPRA model functions
│ ├── meteo.py # Meteorological data utilities
│ └── cli.py # Command-line interface
├── tests/ # Test suite
│ ├── __init__.py
│ ├── test_core.py # Core functionality tests
│ └── test_meteo.py # Meteorological data tests
├── examples/ # Example notebooks and demos
│ ├── SOPRA_Demo.ipynb # Main demonstration notebook
│ ├── SOPRA_Demo_backup.ipynb # Backup notebook
│ ├── stations.txt # Station metadata
│ └── README.md # Examples documentation
├── data/ # Test data and outputs
│ ├── input/ # Input meteorological data
│ │ └── sopra_in/ # Standard format meteo files (2004-2024)
│ ├── output/ # Model outputs
│ │ ├── output_run_Pascal/ # Pascal reference results
│ │ └── output_run_Python/ # Python implementation results
│ └── README.md # Data documentation
├── Makefile # Build and test automation
├── pyproject.toml # Package configuration and metadata
└── README.md # This file
🚀 Quick Start
Using the Makefile (Recommended)
# Install all dependencies
make install-all
# Run unit tests (31 tests, 71% coverage)
make test-unit
# Execute demo notebook
make test-notebook
# Clean up
make clean
Using the Package
import sopra
from sopra import core, meteo
# Initialize SOPRA model
constants = core.assign_const_and_var_gfune()
values = core.init_value_gfune()
# Load meteorological data
import pandas as pd
meteo_df = pd.read_csv('sopra_in/metaig24.std', sep='\t', header=None,
names=['day', 'hour', 'temp_air', 'solar_rad', 'temp_soil'])
# Run simulation for one time step
result = core.update_gfune(
values=values, day=1, hour=0, temp_air=10.0,
solar_rad=100.0, temp_soil=8.0,
curr_param=None, constants=constants
)
print(f"Simulation result: {result}")
Demo Notebook
# Launch Jupyter notebook
jupyter notebook SOPRA_Demo.ipynb
The demo notebook provides:
- Complete walkthrough of the SOPRA model
- Meteorological data processing examples
- Population dynamics visualization
- Validation against Pascal reference results
Command Line Tools
# Verify package integrity
sopra-verify
📊 Data Format
Input Data (.std files)
- Format: Tab-separated values, no headers
- Columns:
day,hour,temp_air,solar_rad,temp_soil - Units: day (1-365), hour (0-23), temperature (°C), solar radiation (W/m²)
- Resolution: Hourly meteorological data
Output Data
- Population stages: pupae, adults, eggs, larvae, diapause individuals
- Temporal resolution: Hourly time series with daily summaries
- Validation metrics: Comparison with Pascal reference results
🔬 Model Description
Scientific Background
- Species: Grapholita funebrana (plum fruit moth)
- Model type: Temperature-dependent population dynamics with delayed response
- Life cycle: Overwintering → spring adults → first generation → summer adults → second generation → diapause
Key Features
- Temperature-dependent development: Linear rate relationships
- Delayed response models: ODE system for stage transitions
- Multi-generational lifecycle: Two generations per year
- Trunk temperature calculation: Estimates bark temperature for pupae development
Model Functions
| Category | Functions | Description |
|---|---|---|
| Core | update_gfune() |
Main simulation step |
| Environment | rate(), get_trunk_temp() |
Temperature processing |
| Initialization | assign_const_and_var_gfune(), init_value_gfune() |
Model setup |
| Population | del_loop_fun(), block_delay_stage() |
Population dynamics |
🏢 Included Stations (2024 Dataset)
| Code | Station Name | Location |
|---|---|---|
| AIG | Aigle | Western Switzerland |
| BAS | Basel / Binningen | Northern Switzerland |
| BER | Bern / Zollikofen | Central Switzerland |
| BUS | Buchs / Aarau | Central Switzerland |
| CGI | Nyon / Changins | Western Switzerland |
| GUT | Güttingen | Eastern Switzerland |
| MAG | Magadino / Cadenazzo | Southern Switzerland |
| PAY | Payerne | Western Switzerland |
| REH | Zürich / Affoltern | Central Switzerland |
| SIO | Sion | Valais |
| STG | St. Gallen | Eastern Switzerland |
| VAD | Vaduz | Liechtenstein |
| WAE | Wädenswil | Central Switzerland |
✅ Validation Results
The Python implementation has been thoroughly validated against the original Pascal version:
- Precision: Maximum differences < 1e-6 (excellent precision)
- Coverage: All 13 stations for 2024 validated successfully
- Life stages: All population stages match Pascal reference
- Seasonal dynamics: Correct timing of emergence, reproduction, and diapause
🛠 Requirements
Python Dependencies
pip install pandas numpy matplotlib pathlib
Python Version
- Python 3.7 or higher
- Tested with Python 3.8+
System Requirements
- Windows/Linux/macOS
- Minimum 1GB RAM
- 100MB disk space
⚙️ Configuration
Environment Variables
For portable deployment across different systems, configure these environment variables:
# Set path to meteorological data archive
export SOPRA_METEO_ARCHIVE_PATH="/path/to/your/meteo/archive"
# Set path to Pascal reference data (for validation)
export SOPRA_PASCAL_REFERENCE_PATH="/path/to/pascal/reference.csv"
Windows:
set SOPRA_METEO_ARCHIVE_PATH=C:\path\to\your\meteo\archive
set SOPRA_PASCAL_REFERENCE_PATH=C:\path\to\pascal\reference.csv
Default Behavior
If environment variables are not set, the system will:
- Try platform-specific default paths (if they exist)
- Fall back to relative paths in the current directory
- Look for
sopra_in/directory for meteorological data - Look for
output_run_Pascal/gfu_all_years.csvfor Pascal reference data
This ensures the package works out-of-the-box for development while remaining portable for deployment.
Network Environment Detection
The SOPRA Demo notebook automatically detects the runtime environment:
🏢 Agroscope Network Environment:
- Accesses meteorological archive for comprehensive data processing
- Converts Excel files to .std format for validation
- Full functionality including historical data analysis
🌐 External Environment:
- Automatically skips archive-dependent operations
- Uses provided sample
.stdfiles insopra_in/directory - Full model validation and simulation capabilities maintained
- External users can add their own
.stdfiles as needed
For External Users:
- ✅ No additional setup required - the notebook handles everything automatically
- ✅ Complete functionality available with included sample data
- ✅ Easy data integration - just add
.stdfiles tosopra_in/directory - ✅ Full validation - Python vs Pascal comparison works with provided data
📖 Usage Examples
1. Single Station Simulation
# Load data and run simulation
meteo_data = read_meteo_file("sopra_in/metaig24.std")
results = run_sopra_model(meteo_data, "aig")
print(f"Simulated {len(results)} days for Aigle")
2. Population Analysis
# Analyze population peaks
population_cols = ['pupae_w', 'adults_w', 'eggs1', 'larvae1', 'diap']
for col in population_cols:
peak_value = results[col].max()
peak_day = results.loc[results[col].idxmax(), 'day']
print(f"{col}: {peak_value:.6f} on day {peak_day}")
3. Validation Against Pascal
# Compare with Pascal reference
comparison = validate_python_vs_pascal("aig", 2024)
print("Validation completed!")
<EFBFBD> API Documentation
sopra.core Module
The sopra.core module contains the main SOPRA model functions:
from sopra import core
# Model initialization
constants = core.assign_const_and_var_gfune() # Initialize constants
values = core.init_value_gfune() # Initialize state variables
# Core simulation functions
result = core.update_gfune(values, day, hour, temp_air, solar_rad, temp_soil)
trunk_temps = core.get_trunk_temp(day, temp_air, solar_rad)
dev_rate = core.rate(b1, b2, temp)
Key Functions:
assign_const_and_var_gfune(): Initialize biological and physical constantsinit_value_gfune(): Initialize population values for all life stagesupdate_gfune(): Execute one simulation time stepget_trunk_temp(): Compute trunk temperature from meteorological datarate(): Calculate temperature-dependent development rates
sopra.meteo Module
The sopra.meteo module provides meteorological data utilities:
from sopra import meteo
# Station information
stations = meteo.STATIONS
station_info = meteo.get_station_info('AIG')
# File discovery and validation
file_path = meteo.discover_meteo_file(2024, 'AIG', 'Aigle', 'Aigle')
is_valid, message = meteo.validate_meteo_file(file_path)
Key Functions:
discover_meteo_file(): Find meteorological data filesvalidate_meteo_file(): Validate data file format and completenessget_station_info(): Get station metadata by codeget_cross_platform_paths(): Handle platform-specific paths
🧪 Development and Testing
Development Installation
# Install with development tools
pip install -e .[dev]
# Run tests (when available)
pytest
# Code formatting
black src/sopra/
flake8 src/sopra/
# Type checking
mypy src/sopra/
Building the Package
# Build distribution packages
python -m build
# Install from built package
pip install dist/sopra-1.0.0-py3-none-any.whl
Custom Meteorological Data
To use your own meteorological data:
- Format data as tab-separated
.stdfiles - Place in
sopra_in/directory - Use naming convention:
met{station}{year}.std
Multiple Years
To process multiple years:
- Add historical
.stdfiles tosopra_in/ - Use the validation functions for cross-year analysis
- Compare results across different years
Custom Parameters
To modify model parameters:
- Edit constants in
assign_const_and_var_gfune() - Adjust initial values in
init_value_gfune() - Re-run simulations with new parameters
📚 References
- Original Pascal SOPRA implementation
- Swiss meteorological station network (MeteoSwiss)
- Grapholita funebrana biological parameters from experimental studies
💡 Support
Common Issues
Q: Import errors when loading functions
A: Ensure all .py files are in the same directory as your notebook
Q: Missing meteorological data
A: Check that .std files exist in sopra_in/ directory
Q: Validation fails
A: Verify Pascal reference data is available in output_run_Pascal/
File Structure Verification
Run this code to verify package integrity:
import os
required_files = [
'grapholita_fun_utils.py',
'sopra_meteo_utils.py',
'stations.txt',
'sopra_in/',
'output_run_Pascal/gfu_all_years.csv'
]
for file_path in required_files:
status = "✅" if os.path.exists(file_path) else "❌"
print(f"{status} {file_path}")
🧪 Development and Testing
Running Tests
The project includes a comprehensive test suite with 71% code coverage.
# Run all unit tests with coverage report
make test-unit
# Run specific test file
pytest tests/test_core.py -v
# Run with detailed coverage report
pytest --cov=sopra --cov-report=html
Test Coverage:
src/sopra/__init__.py: 100%src/sopra/core.py: 86%src/sopra/meteo.py: 42%- Overall: 71%
Test Suite (31 tests):
- ✅ Core utility functions (rate calculations, temperature modeling)
- ✅ Model initialization and configuration
- ✅ Delay and stage progression functions
- ✅ Main update loop and population dynamics
- ✅ Meteorological data handling
- ✅ Station information and file validation
Development Installation
# Install with development tools
make install-dev
# Or using pip directly
pip install -e .[dev]
# Code formatting
black src/sopra/
flake8 src/sopra/
# Type checking
mypy src/sopra/
Building the Package
# Build distribution packages
python -m build
# Install from built package
pip install dist/sopra-1.0.0-py3-none-any.whl
📊 Validation & Verification
Package Verification
# Verify package integrity
sopra-verify
# Or from Python
python verify_package.py
Pascal Reference Validation
The package includes validation against Pascal reference results in output_run_Pascal/gfu_all_years.csv. Maximum differences have been asssessed (error max < 10^{⁻2}), demonstrating excellent precision.
🌍 Station Coverage
The package includes 2024 meteorological data for 13 Swiss stations:
| Code | Station | Records | Code | Station | Records |
|---|---|---|---|---|---|
| AIG | Aigle | 8,702 | PAY | Payerne | 8,657 |
| BAS | Basel | 8,702 | REH | Zürich/Affoltern | 8,702 |
| BER | Bern | 8,702 | SIO | Sion | 8,699 |
| BUS | Buchs/Aarau | 8,702 | STG | St. Gallen | 8,703 |
| CGI | Nyon/Changins | 8,616 | VAD | Vaduz | 8,703 |
| GUT | Güttingen | 8,638 | WAE | Wädenswil | 8,648 |
| MAG | Magadino | 8,703 | Total | 112,877 |
📝 Credit and licence
The original SOPRA source codes (in Pascal) were written by Benno Graf and Jörg Samietz (Agroscope, Switzerland). This includes but is not limited to the Grapholita funebrana model.
This Python implementation has been written by Matthieu Wilhelm (Agroscope, Switzerland).
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
🎉 Ready to Use
This package provides everything needed to run the SOPRA Grapholita funebrana model in Python. The implementation is validated, documented, and ready for operational use in pest management and research applications.
Start with SOPRA_Demo.ipynb for a complete walkthrough!
