mekosotto Claude Sonnet 4.6 commited on
Commit
f45c02a
·
1 Parent(s): 4fff9d2

test(fusion): end-to-end smoke + README section

Browse files

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

Files changed (2) hide show
  1. README.md +13 -0
  2. tests/fusion/test_end_to_end.py +46 -0
README.md CHANGED
@@ -41,6 +41,19 @@ short_description: Living decision system for BBB, EEG, and MRI clinical ML
41
  | 8 | Grand Finale (Multi-Modal Agents, Track 5 & Public Deploy) | Multi-modal explainers + experiments + deploy surface | Shipped |
42
  | 9 | Agent/RAG hardening + MRI DL decision layer | Guarded orchestration + `POST /predict/mri` ONNX surface | Shipped — 242 passed, 2 skipped |
43
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  ## Quick Start
45
 
46
  **Prerequisite:** Python 3.10–3.12. The pinned `requirements.txt` has no cp313+ wheels;
 
41
  | 8 | Grand Finale (Multi-Modal Agents, Track 5 & Public Deploy) | Multi-modal explainers + experiments + deploy surface | Shipped |
42
  | 9 | Agent/RAG hardening + MRI DL decision layer | Guarded orchestration + `POST /predict/mri` ONNX surface | Shipped — 242 passed, 2 skipped |
43
 
44
+ ### Fusion Engine
45
+
46
+ `POST /fusion/predict` (and the agent tool `run_fusion`) combines whichever of
47
+ MRI, EEG, and clinical-test scores (MMSE, MoCA, UPDRS, gait, age) the doctor
48
+ has uploaded into a per-disease confidence (Alzheimer's, Parkinson's, other)
49
+ with full attribution showing how much each modality contributed. Missing
50
+ modalities are skipped, not imputed — the engine renormalises onto whichever
51
+ inputs are present so absence naturally lowers confidence rather than
52
+ silently inflating it. Weights live in `src/fusion/weights.py` and are
53
+ heuristic — adjust there. **BBB is intentionally NOT a fusion modality**:
54
+ it is a researcher-side concern (drug permeability) and stays decoupled
55
+ from disease classification.
56
+
57
  ## Quick Start
58
 
59
  **Prerequisite:** Python 3.10–3.12. The pinned `requirements.txt` has no cp313+ wheels;
tests/fusion/test_end_to_end.py ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """End-to-end: agent calls run_fusion with realistic inputs, top disease is sane."""
2
+ from __future__ import annotations
3
+
4
+ import pytest
5
+
6
+ from src.agents.tools import build_default_tools
7
+
8
+
9
+ @pytest.mark.parametrize(
10
+ "scenario,expected_top",
11
+ [
12
+ # Strong AD signal: low MMSE + MRI flags alzheimers.
13
+ (
14
+ {
15
+ "mri": {
16
+ "label_text": "alzheimers", "label": 1, "confidence": 0.85,
17
+ "probabilities": [
18
+ {"label_text": "control", "probability": 0.15},
19
+ {"label_text": "alzheimers", "probability": 0.85},
20
+ ],
21
+ },
22
+ "clinical": {"mmse": 14.0, "age_years": 79.0},
23
+ },
24
+ "alzheimers",
25
+ ),
26
+ # Strong PD signal: high UPDRS + slow gait + EEG flags parkinsons.
27
+ (
28
+ {
29
+ "eeg": {
30
+ "label_text": "parkinsons", "label": 1, "confidence": 0.78,
31
+ "probabilities": [
32
+ {"label_text": "control", "probability": 0.22},
33
+ {"label_text": "parkinsons", "probability": 0.78},
34
+ ],
35
+ },
36
+ "clinical": {"updrs": 80.0, "gait_speed_m_s": 0.4, "age_years": 70.0},
37
+ },
38
+ "parkinsons",
39
+ ),
40
+ ],
41
+ )
42
+ def test_realistic_scenarios_pick_correct_top_disease(scenario, expected_top) -> None:
43
+ tools = {t.name: t for t in build_default_tools(rag_index_dir=None)}
44
+ tool = tools["run_fusion"]
45
+ out = tool.execute(tool.input_model.model_validate(scenario))
46
+ assert out.top_disease == expected_top