analysis.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. """AI Result Analysis router (P3-M4).
  2. Endpoints for AI-powered simulation result analysis,
  3. multi-fidelity calibration, confidence grading, and convergence checks.
  4. """
  5. from typing import Dict, Any, Optional, List
  6. from fastapi import APIRouter, HTTPException
  7. from pydantic import BaseModel, Field
  8. from ..services.result_analyst import get_result_analyst, FIDELITY_LEVELS
  9. router = APIRouter(prefix="/api/analysis", tags=["Result Analysis"])
  10. class AnalyzeRequest(BaseModel):
  11. """Request for result analysis."""
  12. results: List[Dict[str, Any]] = Field(..., description="List of simulation result dicts")
  13. targets: Optional[Dict[str, float]] = Field(default=None, description="Target values for key metrics")
  14. fidelity: str = Field(default="L3", description="Simulation fidelity level (L0-L4)")
  15. scan_parameters: Optional[List[str]] = Field(default=None, description="List of scanned parameter names")
  16. class CalibrateRequest(BaseModel):
  17. """Request for multi-fidelity calibration."""
  18. metric: str = Field(..., description="Metric name (tavg_nm, efficiency_pct, etc.)")
  19. value: float = Field(..., description="Raw value from simulation")
  20. fidelity: str = Field(..., description="Fidelity level (L0-L4)")
  21. class UpdateCalibrationRequest(BaseModel):
  22. """Request to update calibration factors."""
  23. low_fidelity_results: Dict[str, float]
  24. high_fidelity_results: Dict[str, float]
  25. low_fidelity: str
  26. high_fidelity: str = Field(default="L4")
  27. @router.post("/analyze")
  28. def analyze_results(request: AnalyzeRequest):
  29. """Analyze simulation results with AI and quantitative methods.
  30. Returns comprehensive analysis including:
  31. - Summary and key metrics
  32. - Target comparison
  33. - Multi-fidelity calibration
  34. - Six convergence criteria checks
  35. - Confidence grade (A-D)
  36. - AI-powered trend analysis and optimization suggestions
  37. """
  38. if not request.results:
  39. raise HTTPException(status_code=400, detail="No results provided")
  40. if request.fidelity not in FIDELITY_LEVELS:
  41. raise HTTPException(status_code=400, detail=f"Invalid fidelity level: {request.fidelity}. Use L0-L4.")
  42. try:
  43. analyst = get_result_analyst()
  44. result = analyst.analyze(
  45. results=request.results,
  46. targets=request.targets,
  47. fidelity=request.fidelity,
  48. scan_parameters=request.scan_parameters,
  49. )
  50. return result
  51. except Exception as e:
  52. raise HTTPException(status_code=500, detail=f"Analysis failed: {str(e)}")
  53. @router.post("/calibrate")
  54. def calibrate_result(request: CalibrateRequest):
  55. """Calibrate a low-fidelity result to high-fidelity equivalent.
  56. Uses multi-fidelity calibration factors to correct known biases
  57. between different simulation fidelity levels.
  58. """
  59. if request.fidelity not in FIDELITY_LEVELS:
  60. raise HTTPException(status_code=400, detail=f"Invalid fidelity level: {request.fidelity}")
  61. analyst = get_result_analyst()
  62. result = analyst.calibrator.calibrate(request.metric, request.value, request.fidelity)
  63. return result
  64. @router.post("/calibration/update")
  65. def update_calibration(request: UpdateCalibrationRequest):
  66. """Update calibration factors using paired low-high fidelity results.
  67. When you have both low-fidelity and high-fidelity results for the
  68. same design point, use this to refine the calibration factors.
  69. """
  70. if request.low_fidelity not in FIDELITY_LEVELS:
  71. raise HTTPException(status_code=400, detail=f"Invalid low fidelity: {request.low_fidelity}")
  72. if request.high_fidelity not in FIDELITY_LEVELS:
  73. raise HTTPException(status_code=400, detail=f"Invalid high fidelity: {request.high_fidelity}")
  74. analyst = get_result_analyst()
  75. analyst.calibrator.update_calibration(
  76. low_fidelity_results=request.low_fidelity_results,
  77. high_fidelity_results=request.high_fidelity_results,
  78. low_fidelity=request.low_fidelity,
  79. high_fidelity=request.high_fidelity,
  80. )
  81. return {
  82. "status": "updated",
  83. "current_factors": analyst.calibrator.calibration_factors,
  84. "n_calibration_points": len(analyst.calibrator.calibration_data),
  85. }
  86. @router.get("/fidelity-levels")
  87. def get_fidelity_levels():
  88. """Get available fidelity levels and their properties."""
  89. return {
  90. "levels": FIDELITY_LEVELS,
  91. "description": "Multi-fidelity hierarchy per third-party review. L0=analytic, L4=full 3D transient+thermal.",
  92. }
  93. @router.get("/confidence/scale")
  94. def get_confidence_scale():
  95. """Get confidence grade scale definition."""
  96. return {
  97. "grades": {
  98. "A": {"min_score": 85, "description": "High confidence. High fidelity, sufficient samples, converged, no anomalies."},
  99. "B": {"min_score": 70, "description": "Medium-high confidence. Good fidelity, reasonable samples, mostly converged."},
  100. "C": {"min_score": 50, "description": "Medium confidence. Lower fidelity or limited samples. Use with caution."},
  101. "D": {"min_score": 0, "description": "Low confidence. Insufficient data or significant anomalies. Results unreliable."},
  102. },
  103. "scoring": {
  104. "fidelity": "40% (L4=40, L3=32, L2=24, L1=12, L0=4)",
  105. "sample_density": "25% (min(25, points_per_dimension * 2.5))",
  106. "convergence": "25% (passed_criteria / 6 * 25)",
  107. "anomaly_penalty": "-10% max (min(10, anomalies * 3))",
  108. },
  109. }
  110. @router.get("/convergence/criteria")
  111. def get_convergence_criteria():
  112. """Get six convergence criteria definitions."""
  113. return {
  114. "criteria": [
  115. {"id": 1, "name": "objective_stability", "description": "Objective function change rate < 1% over last 5 points"},
  116. {"id": 2, "name": "optimum_stability", "description": "Optimum location stable over last 5 batches"},
  117. {"id": 3, "name": "surrogate_error", "description": "Surrogate model prediction error < 5%"},
  118. {"id": 4, "name": "constraint_satisfaction", "description": "Constraint satisfaction rate > 95%"},
  119. {"id": 5, "name": "sample_density", "description": "Sample density > 10 points per dimension"},
  120. {"id": 6, "name": "physical_consistency", "description": "All metrics within physically reasonable bounds"},
  121. ],
  122. "convergence_threshold": ">= 4 of 6 criteria passed",
  123. }