Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions API_REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,70 @@ Returns all available labs with descriptions and endpoints.
}
```

### Validation Status

```http
GET /validation/status
```

Returns the current validation gates and coverage metadata used by the simulators.

**Response:**
```json
{
"updated_at": "2025-11-19T17:00:00Z",
"gates": {
"materials": {
"md_error_bounds_percent": 5.0,
"coverage": {
"reference_pairs": 42,
"validation_focus": "NIST + Materials Project cross-checks on steel, aluminum, aerogel, and carbon composites."
},
"ranges": [
{
"name": "temperature",
"keys": ["temperature", "temperature_c"],
"minimum": -50.0,
"maximum": 1200.0,
"units": "°C",
"note": "MD furnace calibration"
},
{
"name": "strain",
"keys": ["strain", "max_strain", "engineering_strain"],
"minimum": 0.0,
"maximum": 0.2,
"units": "ΔL/L",
"note": "Validated tensile strain coverage"
}
]
},
"quantum": {
"coverage": {
"statevector_qubits": {"max": 30, "fidelity_floor": 0.99},
"tensor_network_qubits": {"max": 50, "fidelity_floor": 0.97},
"validated_gate_set": ["h", "x", "rx", "ry", "rz", "cnot", "cz"]
},
"ranges": [
{
"name": "num_qubits",
"keys": ["num_qubits"],
"minimum": 1,
"maximum": 50,
"units": "qubits",
"note": "Statevector exact ≤30; tensor network approximation ≤50"
}
]
}
}
}
```

**Outside-range warnings**

- `/simulate` responses include a `warnings` array when inputs exceed validated limits (e.g., `num_qubits > 30` triggers a tensor-network warning; `temperature > 1200°C` flags MD calibration drift).
- Production endpoints (e.g., spectroscopy encoding) surface the same `warnings` field when data points fall outside the validated 64–8192 sample window.

## Lab Endpoints

### 1. Materials Science Lab
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ Each lab exposes:
- `GET /thresholds` (or similar) - Clinical constants reference
- Interactive docs at `http://localhost:<port>/docs`

### Validation Gates & Warnings
- `GET /validation/status` surfaces the current calibration envelope, including MD error bounds (≤5% on benchmarked materials), validated strain window (0–0.2 ΔL/L), chemistry temperature/pressure gates (250–1200 K, 0.1–50 bar), and quantum coverage (statevector fidelity ≥0.99 up to 30 qubits; tensor network up to 50 qubits).
- Simulation and production responses now add a `warnings` array when requests exceed these validated ranges (e.g., qubit counts above 30, tensile strain over 0.2, spectroscopy inputs outside 64–8192 samples), so clients can downgrade trust or re-parameterize automatically.

## Clinical Validation Status

| Lab | Lines | Clinical Constants | Validated Equations | Production Ready |
Expand Down
9 changes: 8 additions & 1 deletion api/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,19 @@ def list_labs():
"""List all available simulation labs and their capabilities."""
return simulator.list_labs()

@app.get("/validation/status", dependencies=[Depends(get_api_key)])
def validation_status():
"""Return current validation gates and coverage for all labs."""
return simulator.get_validation_status()

@app.post("/simulate", dependencies=[Depends(get_api_key)])
def run_simulation(request: SimulationRequest):
"""Run a simulation in a specified lab."""
try:
results = simulator.run_simulation(request.lab_name, request.experiment_spec)
return {"status": "success", "results": results}
response = {"status": "success", "results": results}
response.update(simulator.get_validation_warnings(request.lab_name, request.experiment_spec))
return response
except ValueError as e:
raise HTTPException(status_code=404, detail=str(e))
except NotImplementedError as e:
Expand Down
20 changes: 18 additions & 2 deletions api/production_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

# Import QuLab AI components
from chemistry_lab.qulab_ai_integration import analyze_molecule_with_provenance
from core.validation_status import get_validation_status, get_validation_warnings
from frequency_lab.qulab_ai_integration import encode_spectrum_array
from qulab_ai.production import (
get_logger,
Expand Down Expand Up @@ -58,6 +59,7 @@ class MoleculeResponse(BaseModel):
citations: List[Dict[str, Any]]
units_checked: bool
units_backend: str
warnings: Optional[List[str]] = None

class SpectrumRequest(BaseModel):
x: List[float] = Field(..., description="X-axis values")
Expand All @@ -68,6 +70,7 @@ class SpectrumResponse(BaseModel):
ml_encoding: Dict[str, float]
alignment: Optional[Dict[str, Any]] = None
data_points: int
warnings: Optional[List[str]] = None

class HealthResponse(BaseModel):
status: str
Expand Down Expand Up @@ -242,6 +245,14 @@ async def get_metrics():
"system_metrics": system_metrics
}

# Validation status endpoint
@app.get("/validation/status", tags=["Validation"])
async def validation_status():
"""
Report current validation gates and coverage metadata.
"""
return get_validation_status()

# Molecule parsing endpoint
@app.post("/api/v1/parse/molecule", response_model=MoleculeResponse, tags=["Chemistry"])
@timed_execution(log_threshold_ms=100.0)
Expand All @@ -261,6 +272,7 @@ async def parse_molecule(request: MoleculeRequest):
request.smiles,
citations=request.citations
)
warnings = get_validation_warnings("chemistry", request.dict())

logger.log_operation(
operation="parse_molecule",
Expand All @@ -269,7 +281,7 @@ async def parse_molecule(request: MoleculeRequest):
n_atoms=result["result"].get("n_atoms", 0)
)

return result
return {**result, "warnings": warnings or None}

except Exception as e:
logger.log_operation(
Expand Down Expand Up @@ -319,6 +331,10 @@ async def encode_spectrum(request: SpectrumRequest):
request.y,
request.caption
)
warnings = get_validation_warnings(
"spectroscopy",
{"data_points": len(request.x)}
)

logger.log_operation(
operation="encode_spectrum",
Expand All @@ -327,7 +343,7 @@ async def encode_spectrum(request: SpectrumRequest):
peaks=result["ml_encoding"]["peaks"]
)

return result
return {**result, "warnings": warnings or None}

except Exception as e:
logger.log_operation(
Expand Down
9 changes: 8 additions & 1 deletion api/v1/endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,19 @@ def list_labs():
"""List all available simulation labs and their capabilities."""
return simulator.list_labs()

@api_router.get("/validation/status", dependencies=[Depends(get_api_key)])
def validation_status():
"""Return current validation gates and coverage for all labs."""
return simulator.get_validation_status()

@api_router.post("/simulate", dependencies=[Depends(get_api_key)])
def run_simulation(request: SimulationRequest):
"""Run a simulation in a specified lab."""
try:
results = simulator.run_simulation(request.lab_name, request.experiment_spec)
return {"status": "success", "results": results}
response = {"status": "success", "results": results}
response.update(simulator.get_validation_warnings(request.lab_name, request.experiment_spec))
return response
except ValueError as e:
raise HTTPException(status_code=404, detail=str(e))
except NotImplementedError as e:
Expand Down
16 changes: 16 additions & 0 deletions core/unified_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from chemistry_lab.chemistry_lab import ChemistryLaboratory
from core.base_lab import BaseLab
from core.config import ConfigManager
from core.validation_status import get_validation_status, get_validation_warnings

class UnifiedSimulator:
"""
Expand All @@ -22,6 +23,7 @@ def __init__(self, config_path: str = "config.yaml"):
"""
self.config_manager = ConfigManager(config_path)
self.labs: Dict[str, BaseLab] = self._load_labs()
self.validation_status = get_validation_status()

def _load_labs(self) -> Dict[str, BaseLab]:
"""
Expand Down Expand Up @@ -64,6 +66,13 @@ def run_simulation(self, lab_name: str, experiment_spec: Dict[str, Any]) -> Dict
lab = self.labs[lab_name]
return lab.run_experiment(experiment_spec)

def get_validation_warnings(self, lab_name: str, experiment_spec: Dict[str, Any]) -> Dict[str, Any]:
"""
Evaluate whether a requested simulation is outside validated ranges.
"""
warnings = get_validation_warnings(lab_name, experiment_spec)
return {"warnings": warnings} if warnings else {}

def get_lab_status(self, lab_name: str) -> Dict[str, Any]:
"""
Get the status of a specific lab.
Expand All @@ -85,6 +94,13 @@ def list_labs(self) -> Dict[str, Dict[str, Any]]:
"""
return {name: lab.get_capabilities() for name, lab in self.labs.items()}

def get_validation_status(self) -> Dict[str, Any]:
"""
Return the current validation gates and coverage metadata.
"""
self.validation_status = get_validation_status()
return self.validation_status

if __name__ == '__main__':
simulator = UnifiedSimulator()

Expand Down
Loading