| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- """AI Result Analysis router (P3-M4).
- Endpoints for AI-powered simulation result analysis,
- multi-fidelity calibration, confidence grading, and convergence checks.
- """
- from typing import Dict, Any, Optional, List
- from fastapi import APIRouter, HTTPException
- from pydantic import BaseModel, Field
- from ..services.result_analyst import get_result_analyst, FIDELITY_LEVELS
- router = APIRouter(prefix="/api/analysis", tags=["Result Analysis"])
- class AnalyzeRequest(BaseModel):
- """Request for result analysis."""
- results: List[Dict[str, Any]] = Field(..., description="List of simulation result dicts")
- targets: Optional[Dict[str, float]] = Field(default=None, description="Target values for key metrics")
- fidelity: str = Field(default="L3", description="Simulation fidelity level (L0-L4)")
- scan_parameters: Optional[List[str]] = Field(default=None, description="List of scanned parameter names")
- class CalibrateRequest(BaseModel):
- """Request for multi-fidelity calibration."""
- metric: str = Field(..., description="Metric name (tavg_nm, efficiency_pct, etc.)")
- value: float = Field(..., description="Raw value from simulation")
- fidelity: str = Field(..., description="Fidelity level (L0-L4)")
- class UpdateCalibrationRequest(BaseModel):
- """Request to update calibration factors."""
- low_fidelity_results: Dict[str, float]
- high_fidelity_results: Dict[str, float]
- low_fidelity: str
- high_fidelity: str = Field(default="L4")
- @router.post("/analyze")
- def analyze_results(request: AnalyzeRequest):
- """Analyze simulation results with AI and quantitative methods.
- Returns comprehensive analysis including:
- - Summary and key metrics
- - Target comparison
- - Multi-fidelity calibration
- - Six convergence criteria checks
- - Confidence grade (A-D)
- - AI-powered trend analysis and optimization suggestions
- """
- if not request.results:
- raise HTTPException(status_code=400, detail="No results provided")
- if request.fidelity not in FIDELITY_LEVELS:
- raise HTTPException(status_code=400, detail=f"Invalid fidelity level: {request.fidelity}. Use L0-L4.")
- try:
- analyst = get_result_analyst()
- result = analyst.analyze(
- results=request.results,
- targets=request.targets,
- fidelity=request.fidelity,
- scan_parameters=request.scan_parameters,
- )
- return result
- except Exception as e:
- raise HTTPException(status_code=500, detail=f"Analysis failed: {str(e)}")
- @router.post("/calibrate")
- def calibrate_result(request: CalibrateRequest):
- """Calibrate a low-fidelity result to high-fidelity equivalent.
- Uses multi-fidelity calibration factors to correct known biases
- between different simulation fidelity levels.
- """
- if request.fidelity not in FIDELITY_LEVELS:
- raise HTTPException(status_code=400, detail=f"Invalid fidelity level: {request.fidelity}")
- analyst = get_result_analyst()
- result = analyst.calibrator.calibrate(request.metric, request.value, request.fidelity)
- return result
- @router.post("/calibration/update")
- def update_calibration(request: UpdateCalibrationRequest):
- """Update calibration factors using paired low-high fidelity results.
- When you have both low-fidelity and high-fidelity results for the
- same design point, use this to refine the calibration factors.
- """
- if request.low_fidelity not in FIDELITY_LEVELS:
- raise HTTPException(status_code=400, detail=f"Invalid low fidelity: {request.low_fidelity}")
- if request.high_fidelity not in FIDELITY_LEVELS:
- raise HTTPException(status_code=400, detail=f"Invalid high fidelity: {request.high_fidelity}")
- analyst = get_result_analyst()
- analyst.calibrator.update_calibration(
- low_fidelity_results=request.low_fidelity_results,
- high_fidelity_results=request.high_fidelity_results,
- low_fidelity=request.low_fidelity,
- high_fidelity=request.high_fidelity,
- )
- return {
- "status": "updated",
- "current_factors": analyst.calibrator.calibration_factors,
- "n_calibration_points": len(analyst.calibrator.calibration_data),
- }
- @router.get("/fidelity-levels")
- def get_fidelity_levels():
- """Get available fidelity levels and their properties."""
- return {
- "levels": FIDELITY_LEVELS,
- "description": "Multi-fidelity hierarchy per third-party review. L0=analytic, L4=full 3D transient+thermal.",
- }
- @router.get("/confidence/scale")
- def get_confidence_scale():
- """Get confidence grade scale definition."""
- return {
- "grades": {
- "A": {"min_score": 85, "description": "High confidence. High fidelity, sufficient samples, converged, no anomalies."},
- "B": {"min_score": 70, "description": "Medium-high confidence. Good fidelity, reasonable samples, mostly converged."},
- "C": {"min_score": 50, "description": "Medium confidence. Lower fidelity or limited samples. Use with caution."},
- "D": {"min_score": 0, "description": "Low confidence. Insufficient data or significant anomalies. Results unreliable."},
- },
- "scoring": {
- "fidelity": "40% (L4=40, L3=32, L2=24, L1=12, L0=4)",
- "sample_density": "25% (min(25, points_per_dimension * 2.5))",
- "convergence": "25% (passed_criteria / 6 * 25)",
- "anomaly_penalty": "-10% max (min(10, anomalies * 3))",
- },
- }
- @router.get("/convergence/criteria")
- def get_convergence_criteria():
- """Get six convergence criteria definitions."""
- return {
- "criteria": [
- {"id": 1, "name": "objective_stability", "description": "Objective function change rate < 1% over last 5 points"},
- {"id": 2, "name": "optimum_stability", "description": "Optimum location stable over last 5 batches"},
- {"id": 3, "name": "surrogate_error", "description": "Surrogate model prediction error < 5%"},
- {"id": 4, "name": "constraint_satisfaction", "description": "Constraint satisfaction rate > 95%"},
- {"id": 5, "name": "sample_density", "description": "Sample density > 10 points per dimension"},
- {"id": 6, "name": "physical_consistency", "description": "All metrics within physically reasonable bounds"},
- ],
- "convergence_threshold": ">= 4 of 6 criteria passed",
- }
|