Files
Atomizer/test_trajectory_extractor.py

49 lines
1.7 KiB
Python
Raw Permalink Normal View History

feat: create SAT3_Trajectory study with Zernike Trajectory Method First production implementation of trajectory-based optimization for M1 mirror. Study Configuration: - Optimizer: TPE (100 trials, 15 startup) - Primary objective: total_filtered_rms_nm (integrated RMS across 20-60 deg) - Logged objectives: coma_rms_nm, astigmatism_rms_nm, trefoil_rms_nm, spherical_rms_nm - Design variables: 11 (full wiffle tree + lateral supports) - Physics validation: R² fit quality monitoring Key Features: - Mode-specific aberration tracking (coma, astigmatism, trefoil, spherical) - Physics-based trajectory model: c_j(θ) = a_j·sin(θ) + b_j·cos(θ) - Sensitivity analysis: axial vs lateral load contributions - OPD correction with focal_length=22000mm - Annular aperture (inner_radius=135.75mm) Validation Results: - Tested on existing M1_Tensor OP2: R²=1.0000 (perfect fit) - Baseline total RMS: 4.30 nm - All 5 angles auto-detected: [20, 30, 40, 50, 60] deg - Dominant mode: spherical (10.51 nm) Files Created: - studies/M1_Mirror/SAT3_Trajectory/README.md (complete documentation) - studies/M1_Mirror/SAT3_Trajectory/STUDY_REPORT.md (results template) - studies/M1_Mirror/SAT3_Trajectory/run_optimization.py (TPE + trajectory extraction) - studies/M1_Mirror/SAT3_Trajectory/1_setup/optimization_config.json (TPE config) - studies/M1_Mirror/SAT3_Trajectory/1_setup/model/ (all NX files copied from M1_Tensor) - test_trajectory_extractor.py (validation script) References: - Physics: docs/physics/ZERNIKE_TRAJECTORY_METHOD.md - Handoff: docs/handoff/SETUP_TRAJECTORY_OPTIMIZATION.md - Extractor: optimization_engine/extractors/extract_zernike_trajectory.py Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-29 12:10:02 -05:00
"""Test the Zernike Trajectory extractor on an existing OP2 file."""
from optimization_engine.extractors.extract_zernike_trajectory import extract_zernike_trajectory
from pathlib import Path
op2_file = Path(r'tests\M1_Tensor\Atomizer_M1_Best_2026-01-29 - Tensor\assy_m1_assyfem1_sim1-solution_1.op2')
print(f'Testing trajectory extractor on: {op2_file}')
print('=' * 60)
try:
result = extract_zernike_trajectory(
op2_file,
reference_angle=20.0,
focal_length=22000.0
)
print('[OK] Extractor ran successfully!')
print()
print(f'Angles detected: {result["angles_deg"]}')
print(f'Reference angle: {result["reference_angle"]} deg')
print(f'Number of angles: {result["n_angles"]}')
print()
print(f'Linear fit R2: {result["linear_fit_r2"]:.4f}')
if result["linear_fit_r2"] > 0.95:
print(' [OK] Excellent fit - physics model validated')
elif result["linear_fit_r2"] > 0.85:
print(' [~] Good fit - some nonlinearity present')
else:
print(' [!] Poor fit - significant nonlinearity')
print()
print('--- Mode-Specific RMS (nm) ---')
print(f'Total Filtered RMS: {result["total_filtered_rms_nm"]:.2f} nm')
print(f'Coma RMS: {result["coma_rms_nm"]:.2f} nm')
print(f'Astigmatism RMS: {result["astigmatism_rms_nm"]:.2f} nm')
print(f'Trefoil RMS: {result["trefoil_rms_nm"]:.2f} nm')
print(f'Spherical RMS: {result["spherical_rms_nm"]:.2f} nm')
print()
print(f'Dominant mode: {result["dominant_mode"]}')
print(f'Mode ranking: {", ".join(result["mode_ranking"][:5])}')
print()
print('[OK] All validation checks passed!')
except Exception as e:
print(f'[ERROR] {e}')
import traceback
traceback.print_exc()
exit(1)