Complete implementation of Protocol 13 featuring real-time web dashboard for monitoring multi-objective optimization studies. ## New Features ### Backend (Python) - Real-time tracking system with per-trial JSON writes - New API endpoints for metadata, optimizer state, and Pareto fronts - Unit inference from objective descriptions - Multi-objective support using Optuna's best_trials API ### Frontend (React + TypeScript) - OptimizerPanel: Real-time optimizer state (phase, strategy, progress) - ParetoPlot: Pareto front visualization with normalization toggle - 3 modes: Raw, Min-Max [0-1], Z-Score standardization - Pareto front line connecting optimal points - ParallelCoordinatesPlot: High-dimensional interactive visualization - Objectives + design variables on parallel axes - Click-to-select, hover-to-highlight - Color-coded feasibility - Dynamic units throughout all visualizations ### Documentation - Comprehensive Protocol 13 guide with architecture, data flow, usage ## Files Added - `docs/PROTOCOL_13_DASHBOARD.md` - `atomizer-dashboard/frontend/src/components/OptimizerPanel.tsx` - `atomizer-dashboard/frontend/src/components/ParetoPlot.tsx` - `atomizer-dashboard/frontend/src/components/ParallelCoordinatesPlot.tsx` - `optimization_engine/realtime_tracking.py` ## Files Modified - `atomizer-dashboard/frontend/src/pages/Dashboard.tsx` - `atomizer-dashboard/backend/api/routes/optimization.py` - `optimization_engine/intelligent_optimizer.py` ## Testing - Tested with bracket_stiffness_optimization_V2 (30 trials, 20 Pareto solutions) - Dashboard running on localhost:3001 - All P1 and P2 features verified working 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
156 lines
4.7 KiB
TypeScript
156 lines
4.7 KiB
TypeScript
/**
|
|
* Intelligent Optimizer Panel - Protocol 13
|
|
* Displays real-time optimizer state: phase, strategy, progress, confidence
|
|
*/
|
|
|
|
import { useEffect, useState } from 'react';
|
|
|
|
interface OptimizerState {
|
|
available: boolean;
|
|
current_phase?: string;
|
|
current_strategy?: string;
|
|
trial_number?: number;
|
|
total_trials?: number;
|
|
is_multi_objective?: boolean;
|
|
latest_recommendation?: {
|
|
strategy: string;
|
|
confidence: number;
|
|
reasoning: string;
|
|
};
|
|
}
|
|
|
|
export function OptimizerPanel({ studyId }: { studyId: string }) {
|
|
const [state, setState] = useState<OptimizerState | null>(null);
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
useEffect(() => {
|
|
const fetchState = async () => {
|
|
try {
|
|
const res = await fetch(`/api/optimization/studies/${studyId}/optimizer-state`);
|
|
if (!res.ok) {
|
|
throw new Error(`HTTP ${res.status}`);
|
|
}
|
|
const data = await res.json();
|
|
setState(data);
|
|
setError(null);
|
|
} catch (err) {
|
|
console.error('Failed to fetch optimizer state:', err);
|
|
setError('Failed to load');
|
|
}
|
|
};
|
|
|
|
fetchState();
|
|
const interval = setInterval(fetchState, 1000); // Update every second
|
|
return () => clearInterval(interval);
|
|
}, [studyId]);
|
|
|
|
if (error) {
|
|
return (
|
|
<div className="bg-dark-700 rounded-lg p-6 border border-dark-600">
|
|
<h3 className="text-lg font-semibold mb-4 text-dark-100">Intelligent Optimizer</h3>
|
|
<div className="text-dark-400 text-sm">
|
|
{error}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (!state?.available) {
|
|
return null;
|
|
}
|
|
|
|
// Format phase name for display
|
|
const formatPhase = (phase?: string) => {
|
|
if (!phase) return 'Unknown';
|
|
return phase
|
|
.split('_')
|
|
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
|
.join(' ');
|
|
};
|
|
|
|
// Format strategy name for display
|
|
const formatStrategy = (strategy?: string) => {
|
|
if (!strategy) return 'Not set';
|
|
return strategy.toUpperCase();
|
|
};
|
|
|
|
const progress = state.trial_number && state.total_trials
|
|
? (state.trial_number / state.total_trials) * 100
|
|
: 0;
|
|
|
|
return (
|
|
<div className="bg-dark-700 rounded-lg p-6 border border-dark-600">
|
|
<h3 className="text-lg font-semibold mb-4 text-dark-100 flex items-center gap-2">
|
|
Intelligent Optimizer
|
|
{state.is_multi_objective && (
|
|
<span className="text-xs bg-purple-500/20 text-purple-300 px-2 py-1 rounded">
|
|
Multi-Objective
|
|
</span>
|
|
)}
|
|
</h3>
|
|
|
|
<div className="space-y-4">
|
|
{/* Phase */}
|
|
<div>
|
|
<div className="text-sm text-dark-300 mb-1">Phase</div>
|
|
<div className="text-lg font-semibold text-primary-400">
|
|
{formatPhase(state.current_phase)}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Strategy */}
|
|
<div>
|
|
<div className="text-sm text-dark-300 mb-1">Current Strategy</div>
|
|
<div className="text-lg font-semibold text-blue-400">
|
|
{formatStrategy(state.current_strategy)}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Progress */}
|
|
<div>
|
|
<div className="text-sm text-dark-300 mb-1">Progress</div>
|
|
<div className="text-lg text-dark-100">
|
|
{state.trial_number || 0} / {state.total_trials || 0} trials
|
|
</div>
|
|
<div className="w-full bg-dark-500 rounded-full h-2 mt-2">
|
|
<div
|
|
className="bg-primary-400 h-2 rounded-full transition-all duration-300"
|
|
style={{ width: `${progress}%` }}
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Confidence (if available) */}
|
|
{state.latest_recommendation && (
|
|
<div>
|
|
<div className="text-sm text-dark-300 mb-1">Confidence</div>
|
|
<div className="flex items-center gap-2">
|
|
<div className="flex-1 bg-dark-500 rounded-full h-2">
|
|
<div
|
|
className="bg-green-400 h-2 rounded-full transition-all duration-300"
|
|
style={{
|
|
width: `${state.latest_recommendation.confidence * 100}%`
|
|
}}
|
|
/>
|
|
</div>
|
|
<span className="text-sm font-mono text-dark-200 min-w-[3rem] text-right">
|
|
{(state.latest_recommendation.confidence * 100).toFixed(0)}%
|
|
</span>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* Reasoning (if available) */}
|
|
{state.latest_recommendation && (
|
|
<div>
|
|
<div className="text-sm text-dark-300 mb-1">Reasoning</div>
|
|
<div className="text-sm text-dark-100 bg-dark-800 rounded p-3 border border-dark-600">
|
|
{state.latest_recommendation.reasoning}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|