Files
closed_loop_audio_test_suite/view_results.py

147 lines
5.3 KiB
Python

#!/usr/bin/env python3
import argparse
import yaml
from pathlib import Path
from datetime import datetime
def print_separator(char='-', length=70):
print(char * length)
def format_value(value, suffix=''):
if isinstance(value, float):
return f"{value:.3f}{suffix}"
return f"{value}{suffix}"
def display_results(yaml_file: Path):
with open(yaml_file, 'r') as f:
data = yaml.safe_load(f)
metadata = data['metadata']
results = data['test_results']
print("\n" + "=" * 70)
print(f" AUDIO TEST RESULTS")
print("=" * 70)
print("\n📋 Test Metadata:")
print_separator()
print(f" Test ID: {metadata['test_id']}")
print(f" Timestamp: {metadata['timestamp']}")
print(f" PCB Version: {metadata['pcb_version']}")
print(f" PCB Revision: {metadata['pcb_revision']}")
print(f" Software Version: {metadata['software_version']}")
if metadata.get('notes'):
print(f" Notes: {metadata['notes']}")
if 'latency_test' in data:
latency = data['latency_test']
print("\n🎯 Latency Test (Chirp):")
print_separator()
if 'error' in latency:
print(f" Error: {latency['error']}")
else:
print(f" Average: {latency['avg']:.3f} ms")
print(f" Min: {latency['min']:.3f} ms")
print(f" Max: {latency['max']:.3f} ms")
print(f" Std Dev: {latency['std']:.4f} ms")
print("\n📊 Frequency Sweep Results:")
print_separator()
header = f"{'Freq (Hz)':<12} {'THD CH1 (%)':<13} {'THD CH2 (%)':<13} {'SNR CH1 (dB)':<14} {'SNR CH2 (dB)':<14}"
print(header)
print(f"{'':12} {'(Loopback)':<13} {'(DUT)':<13} {'(Loopback)':<14} {'(DUT)':<14}")
print_separator()
for result in results:
if 'error' in result:
print(f"{result['frequency_hz']:<12} ERROR: {result['error']}")
else:
freq = result['frequency_hz']
thd_ch1 = format_value(result.get('thd_ch1_loopback_percent', result.get('thd_input_percent', 0)))
thd_ch2 = format_value(result.get('thd_ch2_dut_percent', result.get('thd_output_percent', 0)))
snr_ch1 = format_value(result.get('snr_ch1_loopback_db', result.get('snr_input_db', 0)))
snr_ch2 = format_value(result.get('snr_ch2_dut_db', result.get('snr_output_db', 0)))
print(f"{freq:<12} {thd_ch1:<13} {thd_ch2:<13} {snr_ch1:<14} {snr_ch2:<14}")
print_separator()
valid_results = [r for r in results if 'error' not in r]
if valid_results:
avg_thd_ch1 = sum(r.get('thd_ch1_loopback_percent', r.get('thd_input_percent', 0)) for r in valid_results) / len(valid_results)
avg_thd_ch2 = sum(r.get('thd_ch2_dut_percent', r.get('thd_output_percent', 0)) for r in valid_results) / len(valid_results)
avg_snr_ch1 = sum(r.get('snr_ch1_loopback_db', r.get('snr_input_db', 0)) for r in valid_results) / len(valid_results)
avg_snr_ch2 = sum(r.get('snr_ch2_dut_db', r.get('snr_output_db', 0)) for r in valid_results) / len(valid_results)
print("\n📈 Average Values:")
print_separator()
print(f" THD CH1 (Loopback): {avg_thd_ch1:.3f} %")
print(f" THD CH2 (DUT): {avg_thd_ch2:.3f} %")
print(f" SNR CH1 (Loopback): {avg_snr_ch1:.2f} dB")
print(f" SNR CH2 (DUT): {avg_snr_ch2:.2f} dB")
print("\n" + "=" * 70 + "\n")
def list_all_results(results_dir: Path):
yaml_files = sorted(results_dir.rglob("*_results.yaml"))
if not yaml_files:
print("No test results found.")
return
print("\n" + "=" * 70)
print(" AVAILABLE TEST RESULTS")
print("=" * 70 + "\n")
for yaml_file in yaml_files:
try:
with open(yaml_file, 'r') as f:
data = yaml.safe_load(f)
metadata = data['metadata']
timestamp = datetime.fromisoformat(metadata['timestamp'])
print(f"📄 {yaml_file.name}")
print(f" Date: {timestamp.strftime('%Y-%m-%d %H:%M:%S')}")
print(f" PCB: {metadata['pcb_version']} Rev {metadata['pcb_revision']}")
print(f" SW: {metadata['software_version']}")
if metadata.get('notes'):
print(f" Note: {metadata['notes']}")
print()
except Exception as e:
print(f"⚠️ {yaml_file.name} (corrupted - skipping)")
print()
def main():
parser = argparse.ArgumentParser(description='View PCB test results')
parser.add_argument('file', nargs='?', help='YAML results file to view')
parser.add_argument('--list', action='store_true', help='List all available test results')
parser.add_argument('--results-dir', default='test_results', help='Directory containing results')
args = parser.parse_args()
results_dir = Path(args.results_dir)
if args.list or not args.file:
list_all_results(results_dir)
else:
yaml_file = Path(args.file)
if not yaml_file.exists():
yaml_file = results_dir / args.file
if not yaml_file.exists():
print(f"Error: File not found: {yaml_file}")
return 1
display_results(yaml_file)
if __name__ == '__main__':
main()