- Reorganize dashboard: control panel on top, charts stacked vertically - Add Set Context button to Claude terminal for study awareness - Add conda environment instructions to CLAUDE.md - Fix STUDY_REPORT.md location in generate-report.md skill - Claude terminal now sends study context with skills reminder 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
12 KiB
12 KiB
Generate Report Skill
Last Updated: December 3, 2025 Version: 1.1 - Optimization Results Analysis and Reporting (Dashboard Integration)
You are helping the user understand and communicate optimization results.
Purpose
Generate comprehensive reports from completed optimization studies:
- Pareto front analysis and visualization
- Design space exploration insights
- Constraint satisfaction analysis
- Engineering recommendations
- Export-ready summaries
Triggers
- "generate report"
- "show results"
- "analyze the optimization"
- "what did we find?"
- "summarize the study"
- "export results"
Prerequisites
- Completed optimization study with
study.db - At least 10 completed trials (for meaningful analysis)
- Optional:
optimization_config.jsonfor context
Report Types
1. Quick Summary
Fast overview of key findings (default).
2. Full Technical Report
Comprehensive analysis with all visualizations.
3. Executive Summary
High-level findings for stakeholders.
4. Export Package
Data files for external analysis.
Execution Steps
Step 1: Load Study Data
import optuna
import json
from pathlib import Path
def load_study_data(study_name: str):
"""Load all optimization data for analysis."""
study_dir = Path(f"studies/{study_name}")
# Load Optuna study
storage = f"sqlite:///{study_dir / '2_results' / 'study.db'}"
study = optuna.load_study(study_name=study_name, storage=storage)
# Load config for context
config_path = study_dir / "1_setup" / "optimization_config.json"
config = json.loads(config_path.read_text()) if config_path.exists() else {}
return {
'study': study,
'config': config,
'n_trials': len(study.trials),
'n_completed': len([t for t in study.trials if t.state == optuna.trial.TrialState.COMPLETE]),
'is_multi_objective': len(study.directions) > 1
}
Step 2: Analyze Results
For Multi-Objective (Pareto Analysis)
def analyze_pareto_front(study):
"""Extract and analyze Pareto-optimal solutions."""
pareto_trials = study.best_trials
results = {
'n_pareto': len(pareto_trials),
'designs': [],
'ranges': {},
'trade_offs': []
}
for trial in pareto_trials:
design = {
'trial_number': trial.number,
'objectives': trial.values,
'parameters': trial.params,
'user_attrs': trial.user_attrs
}
results['designs'].append(design)
# Calculate objective ranges on Pareto front
if pareto_trials:
obj_names = ['mass', 'frequency'] # From config
for i, name in enumerate(obj_names):
values = [t.values[i] for t in pareto_trials]
results['ranges'][name] = {
'min': min(values),
'max': max(values),
'spread': max(values) - min(values)
}
return results
For Single-Objective
def analyze_single_objective(study):
"""Analyze single-objective optimization results."""
best = study.best_trial
return {
'best_value': best.value,
'best_params': best.params,
'convergence': get_convergence_history(study),
'improvement_rate': calculate_improvement_rate(study)
}
Step 3: Constraint Analysis
def analyze_constraints(study, config):
"""Analyze constraint satisfaction across trials."""
constraints = config.get('constraints', [])
results = {
'total_trials': len(study.trials),
'feasible': 0,
'infeasible': 0,
'violations': {}
}
for constraint in constraints:
results['violations'][constraint['name']] = 0
for trial in study.trials:
if trial.state != optuna.trial.TrialState.COMPLETE:
continue
is_feasible = trial.user_attrs.get('feasible', True)
if is_feasible:
results['feasible'] += 1
else:
results['infeasible'] += 1
# Track which constraints were violated
for constraint in constraints:
if constraint['name'] in trial.user_attrs.get('violated_constraints', []):
results['violations'][constraint['name']] += 1
results['feasibility_rate'] = results['feasible'] / results['total_trials'] * 100
return results
Step 4: Generate Visualizations
Describe what plots to generate (actual generation done via Python scripts):
- Pareto Front Plot: Mass vs Frequency with feasibility coloring
- Parallel Coordinates: All design variables with objective coloring
- Parameter Importance: Which variables most affect objectives
- Convergence History: Best value over trials
- Design Space Coverage: Parameter distributions
Step 5: Generate Report Text
Output Format: Quick Summary
OPTIMIZATION RESULTS: {study_name}
===================================
Study Info:
Protocol: Protocol 11 (Multi-Objective NSGA-II)
Trials: 30 completed
Duration: 14m 23s
Feasibility Rate: 80%
PARETO FRONT (8 optimal designs)
--------------------------------
| # | Mass (g) | Freq (Hz) | Feasible | Notes |
|---|----------|-----------|----------|-------|
| 1 | 231 | 118 | Yes | Lightest |
| 2 | 248 | 128 | Yes | |
| 3 | 265 | 138 | Yes | Balanced |
| 4 | 282 | 148 | Yes | |
| 5 | 298 | 156 | Yes | Stiffest |
Trade-off Summary:
- Mass range: 231g - 298g (67g spread)
- Frequency range: 118Hz - 156Hz (38Hz spread)
- Trade-off rate: ~1.7g per Hz
BEST DESIGNS BY OBJECTIVE
-------------------------
Lightest Design (#1):
Mass: 231g, Frequency: 118Hz
Parameters:
beam_half_core_thickness: 8.2mm
beam_face_thickness: 1.1mm
holes_diameter: 42mm
hole_count: 10
Stiffest Design (#5):
Mass: 298g, Frequency: 156Hz
Parameters:
beam_half_core_thickness: 18.5mm
beam_face_thickness: 2.8mm
holes_diameter: 22mm
hole_count: 6
CONSTRAINT ANALYSIS
-------------------
Constraints checked:
- max_displacement < 5mm: 24/30 satisfied (80%)
- max_stress < 200 MPa: 28/30 satisfied (93%)
Most common violation: Displacement (6 trials)
Occurred when: holes_diameter > 40mm AND face_thickness < 1.5mm
PARAMETER INSIGHTS
------------------
Most influential on mass:
1. holes_diameter (negative correlation)
2. beam_face_thickness (positive)
3. beam_half_core_thickness (positive)
Most influential on frequency:
1. beam_half_core_thickness (positive)
2. holes_diameter (negative)
3. beam_face_thickness (moderate positive)
RECOMMENDATIONS
---------------
1. For lightweight priority:
- Use larger holes (40-45mm)
- Minimize face thickness (1.0-1.5mm)
- Accept frequency around 120Hz
2. For stiffness priority:
- Use smaller holes (20-25mm)
- Increase core thickness (18-20mm)
- Accept mass around 300g
3. Balanced recommendation:
- Design #3 offers good compromise
- 265g mass with 138Hz frequency
- 13% lighter than stiffest, 17% stiffer than lightest
NEXT STEPS
----------
1. Export selected designs: python export_pareto.py --designs 1,3,5
2. Validate in NX: Open model with exported parameters
3. Continue optimization: python run_optimization.py --trials 50 --resume
4. Enable NN acceleration: Add --enable-nn flag for faster exploration
Output Format: Full Technical Report
Generate markdown file with:
# {study_name} Optimization Report
Generated: {timestamp}
Protocol: {protocol}
## Executive Summary
[2-3 paragraph overview]
## Study Configuration
### Design Variables
[Table of variables, bounds, types]
### Objectives
[Table of objectives, goals, targets]
### Constraints
[Table of constraints, thresholds]
## Results Analysis
### Pareto Front
[Detailed table of all Pareto-optimal designs]

### Design Space Exploration
[Parallel coordinates plot]

### Convergence History
[Plot of best values over trials]
### Parameter Importance
[SHAP or importance analysis]
## Constraint Satisfaction
[Detailed constraint analysis]
## Engineering Recommendations
[Specific design recommendations]
## Appendix
### All Trial Data
[Exportable CSV reference]
### Methodology Notes
[Protocol details, sampler settings]
Export Package
Generate files:
{study_name}_export/
├── pareto_designs.csv # All Pareto-optimal designs
├── all_trials.csv # Complete trial history
├── optimization_summary.json # Machine-readable summary
├── pareto_front.png # Visualization
├── parallel_coords.png # Visualization
└── README.md # Export documentation
Error Handling
| Error | Recovery |
|---|---|
| No completed trials | Suggest running more trials |
| No feasible designs | Analyze constraint violations |
| Study not found | List available studies |
| Incomplete data | Note missing fields |
Integration with Other Skills
- After report →
/export-resultsfor specific designs - If poor results →
/troubleshootfor analysis - To continue →
/run-optimizationwith --resume
Example Conversation
USER: Show me the results for uav_arm_optimization
CLAUDE: I'll generate a report for the UAV arm optimization study...
[Loads study data]
OPTIMIZATION RESULTS: uav_arm_optimization
==========================================
Found 30 completed trials with 8 Pareto-optimal designs.
PARETO FRONT SUMMARY
--------------------
| Design | Mass (g) | Freq (Hz) | Trade-off |
|--------|----------|-----------|-----------|
| #1 | 231 | 118 | Lightest |
| #3 | 265 | 138 | Balanced |
| #5 | 298 | 156 | Stiffest |
Key Finding: You can save 67g (23%) by accepting 38Hz (24%)
lower frequency.
RECOMMENDATION: Design #3 (265g, 138Hz) offers the best balance
for a camera gimbal application where both vibration and weight
matter.
Would you like me to:
1. Generate a full technical report with visualizations?
2. Export the top designs for validation in NX?
3. Continue optimization to explore more designs?
Dashboard Integration (December 2025)
When a STUDY_REPORT.md file is generated, it can be viewed directly in the Atomizer Dashboard:
- Save report to:
studies/{study_name}/STUDY_REPORT.md(study root folder) - View in dashboard: Click "Study Report" button on the dashboard
- Features:
- Full markdown rendering with proper typography
- Math equation support via KaTeX (
$...$inline,$$...$$block) - Tables, code blocks, task lists
- Live refresh button for updates during analysis
Report Format for Dashboard
Use standard markdown with optional LaTeX math:
# Study Report: {study_name}
## Summary
The optimization achieved a **{improvement}%** improvement in objective.
## Results
| Trial | Objective | Improvement |
|-------|-----------|-------------|
| 0 | 100.0 | baseline |
| 10 | 85.5 | 14.5% |
## Mathematical Formulation
The RMS wavefront error is calculated as:
$$\text{RMS} = \sqrt{\frac{1}{N}\sum_{i=1}^{N}c_i^2}$$
where $c_i$ are the Zernike coefficients.
Notes
- Reports should be actionable, not just data dumps
- Always provide engineering context and recommendations
- Consider the user's stated goals when highlighting results
- Visualizations should be generated via Python scripts
- Export formats should be compatible with common tools (Excel, etc.)
- Use STUDY_REPORT.md for dashboard-viewable reports with math support