feat: Add post-optimization tools and mandatory best design archiving

New Tools (tools/):
- analyze_study.py: Generate comprehensive optimization reports
- find_best_iteration.py: Find best iteration folder, optionally copy it
- archive_best_design.py: Archive best design to 3_results/best_design_archive/<timestamp>/

Protocol Updates:
- OP_02_RUN_OPTIMIZATION.md v1.1: Add mandatory archive_best_design step
  in Post-Run Actions. This MUST be done after every optimization run.

V14 Updates:
- run_optimization.py: Auto-archive best design at end of optimization
- optimization_config.json: Expand bounds for V14 continuation
  - lateral_outer_angle: min 13->11 deg (was at 4.7%)
  - lateral_inner_pivot: min 7->5 mm (was at 8.1%)
  - lateral_middle_pivot: max 23->27 mm (was at 99.4%)
  - whiffle_min: max 60->72 mm (was at 96.3%)

Usage:
  python tools/analyze_study.py m1_mirror_adaptive_V14
  python tools/find_best_iteration.py m1_mirror_adaptive_V14
  python tools/archive_best_design.py m1_mirror_adaptive_V14

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Antoine
2025-12-12 10:28:35 -05:00
parent 70ac34e3d3
commit 1bb201e0b7
6 changed files with 913 additions and 15 deletions

View File

@@ -1,7 +1,7 @@
{
"$schema": "Atomizer M1 Mirror TPE Optimization V14",
"study_name": "m1_mirror_adaptive_V14",
"description": "V14 - TPE single-objective optimization seeded from V11+V12+V13 FEA trials. Weighted-sum objective for efficient convergence.",
"description": "V14 continuation - TPE with expanded bounds based on V14 analysis. 4 params were at bounds: lateral_middle_pivot (99.4%), whiffle_min (96.3%), lateral_outer_angle (4.7%), lateral_inner_pivot (8.1%).",
"source_studies": {
"v11": {
@@ -31,11 +31,12 @@
{
"name": "lateral_outer_angle",
"expression_name": "lateral_outer_angle",
"min": 13.0,
"min": 11.0,
"max": 17.0,
"baseline": 14.64,
"units": "degrees",
"enabled": true
"enabled": true,
"_note": "Expanded min from 13 to 11 (was at 4.7% of range)"
},
{
"name": "lateral_outer_pivot",
@@ -49,20 +50,22 @@
{
"name": "lateral_inner_pivot",
"expression_name": "lateral_inner_pivot",
"min": 7.0,
"min": 5.0,
"max": 12.0,
"baseline": 10.07,
"units": "mm",
"enabled": true
"enabled": true,
"_note": "Expanded min from 7 to 5 (was at 8.1% of range)"
},
{
"name": "lateral_middle_pivot",
"expression_name": "lateral_middle_pivot",
"min": 15.0,
"max": 23.0,
"max": 27.0,
"baseline": 20.73,
"units": "mm",
"enabled": true
"enabled": true,
"_note": "Expanded max from 23 to 27 (was at 99.4% of range)"
},
{
"name": "lateral_closeness",
@@ -77,10 +80,11 @@
"name": "whiffle_min",
"expression_name": "whiffle_min",
"min": 30.0,
"max": 60.0,
"max": 72.0,
"baseline": 40.55,
"units": "mm",
"enabled": true
"enabled": true,
"_note": "Expanded max from 60 to 72 (was at 96.3% of range)"
},
{
"name": "whiffle_outer_to_vertical",

View File

@@ -600,6 +600,32 @@ class TPEOptimizer:
logger.info(f"\nResults saved to {RESULTS_DIR / 'final_results.json'}")
# Archive best design
self._archive_best_design()
def _archive_best_design(self):
"""Archive the best design iteration folder."""
try:
# Import archive tool
tools_dir = Path(__file__).parent.parent.parent / "tools"
sys.path.insert(0, str(tools_dir))
from archive_best_design import archive_best_design
logger.info("\n" + "-" * 70)
logger.info("ARCHIVING BEST DESIGN")
logger.info("-" * 70)
result = archive_best_design(str(Path(__file__).parent))
if result.get('success'):
logger.info(f"[OK] Best design archived to: {result['archive_path']}")
logger.info(f" Trial #{result['trial_number']}, WS={result['weighted_sum']:.2f}")
else:
logger.warning(f"[WARN] Archive skipped: {result.get('reason', 'Unknown')}")
except Exception as e:
logger.error(f"[ERROR] Failed to archive best design: {e}")
# ============================================================================
# Main