This commit includes: 1. Database Configuration Migration: - Migrated from DB.txt (Java JDBC) to .env (python-dotenv) - Added .env.example template with clear variable names - Updated database.py to use environment variables - Added python-dotenv>=1.0.0 to dependencies - Updated .gitignore to exclude sensitive files 2. Validation System (1,294 lines): - comparator.py: Statistical comparison with RMSE, correlation, tolerances - db_extractor.py: Database queries for all sensor types - validator.py: High-level validation orchestration - cli.py: Command-line interface for validation - README.md: Comprehensive validation documentation 3. Validation Features: - Compare Python vs MATLAB outputs from database - Support for all sensor types (RSN, Tilt, ATD) - Statistical metrics: max abs/rel diff, RMSE, correlation - Configurable tolerances (abs, rel, max) - Detailed validation reports - CLI and programmatic APIs 4. Examples and Documentation: - validate_example.sh: Bash script example - validate_example.py: Python programmatic example - Updated main README with validation section - Added validation workflow and troubleshooting guide Benefits: - ✅ No Java driver needed (native Python connectors) - ✅ Secure .env configuration (excluded from git) - ✅ Comprehensive validation against MATLAB - ✅ Statistical confidence in migration accuracy - ✅ Automated validation reports 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
97 lines
3.5 KiB
Python
Executable File
97 lines
3.5 KiB
Python
Executable File
#!/usr/bin/env python
|
|
"""
|
|
Example script demonstrating programmatic validation usage.
|
|
|
|
This shows how to use the validation API directly in Python code.
|
|
"""
|
|
|
|
import sys
|
|
from src.common.database import DatabaseConfig, DatabaseConnection
|
|
from src.validation.validator import OutputValidator
|
|
from src.common.logging_utils import setup_logger
|
|
|
|
|
|
def main():
|
|
"""Main validation example."""
|
|
# Setup
|
|
logger = setup_logger('validation_example')
|
|
control_unit_id = 'CU001'
|
|
chain = 'A'
|
|
|
|
logger.info(f"Starting validation for {control_unit_id}/{chain}")
|
|
|
|
try:
|
|
# Connect to database
|
|
db_config = DatabaseConfig()
|
|
with DatabaseConnection(db_config) as conn:
|
|
logger.info("Database connected")
|
|
|
|
# Create validator with custom tolerances
|
|
validator = OutputValidator(
|
|
conn,
|
|
abs_tol=1e-6, # Absolute tolerance
|
|
rel_tol=1e-4, # Relative tolerance (0.01%)
|
|
max_rel_tol=0.01 # Max acceptable (1%)
|
|
)
|
|
|
|
# Example 1: Validate specific sensor type
|
|
logger.info("Example 1: Validating RSN sensors...")
|
|
report = validator.validate_rsn(control_unit_id, chain)
|
|
|
|
print("\n" + "=" * 80)
|
|
print("RSN VALIDATION RESULTS")
|
|
print("=" * 80)
|
|
print(report.generate_report())
|
|
|
|
if report.is_valid():
|
|
logger.info("✓ RSN validation passed")
|
|
else:
|
|
logger.warning("✗ RSN validation failed")
|
|
|
|
# Example 2: Validate all sensors
|
|
logger.info("\nExample 2: Validating all sensors...")
|
|
validator_all = OutputValidator(conn)
|
|
report_all = validator_all.validate_all(control_unit_id, chain)
|
|
|
|
print("\n" + "=" * 80)
|
|
print("COMPREHENSIVE VALIDATION RESULTS")
|
|
print("=" * 80)
|
|
print(report_all.generate_report())
|
|
|
|
# Save report to file
|
|
output_file = f"validation_{control_unit_id}_{chain}.txt"
|
|
report_all.save_report(output_file, include_equivalent=True)
|
|
logger.info(f"Report saved to {output_file}")
|
|
|
|
# Example 3: Access individual results programmatically
|
|
logger.info("\nExample 3: Programmatic access to results...")
|
|
summary = report_all.get_summary()
|
|
|
|
print("\nSummary Statistics:")
|
|
print(f" Identical: {summary['identical']}")
|
|
print(f" Equivalent: {summary['equivalent']}")
|
|
print(f" Different: {summary['different']}")
|
|
print(f" Missing: {summary['missing_matlab'] + summary['missing_python']}")
|
|
print(f" Errors: {summary['error']}")
|
|
|
|
# Check specific fields
|
|
print("\nDetailed Results:")
|
|
for result in report_all.results[:5]: # Show first 5
|
|
print(f"\n{result.field_name}:")
|
|
print(f" Status: {result.status.value}")
|
|
if result.max_abs_diff is not None:
|
|
print(f" Max abs diff: {result.max_abs_diff:.2e}")
|
|
print(f" Max rel diff: {result.max_rel_diff:.2%}")
|
|
print(f" Correlation: {result.correlation:.6f}")
|
|
|
|
# Return success/failure
|
|
return 0 if report_all.is_valid() else 1
|
|
|
|
except Exception as e:
|
|
logger.error(f"Validation error: {e}", exc_info=True)
|
|
return 1
|
|
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main())
|