- 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>
440 lines
12 KiB
Markdown
440 lines
12 KiB
Markdown
# 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:
|
|
1. Pareto front analysis and visualization
|
|
2. Design space exploration insights
|
|
3. Constraint satisfaction analysis
|
|
4. Engineering recommendations
|
|
5. 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.json` for 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
|
|
|
|
```python
|
|
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)
|
|
|
|
```python
|
|
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
|
|
|
|
```python
|
|
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
|
|
|
|
```python
|
|
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):
|
|
|
|
1. **Pareto Front Plot**: Mass vs Frequency with feasibility coloring
|
|
2. **Parallel Coordinates**: All design variables with objective coloring
|
|
3. **Parameter Importance**: Which variables most affect objectives
|
|
4. **Convergence History**: Best value over trials
|
|
5. **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:
|
|
|
|
```markdown
|
|
# {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-results` for specific designs
|
|
- If poor results → `/troubleshoot` for analysis
|
|
- To continue → `/run-optimization` with --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:
|
|
|
|
1. **Save report to**: `studies/{study_name}/STUDY_REPORT.md` (study root folder)
|
|
2. **View in dashboard**: Click "Study Report" button on the dashboard
|
|
3. **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:
|
|
|
|
```markdown
|
|
# 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
|