File size: 2,486 Bytes
f4102c2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
export const API_BASE =
  process.env.NEXT_PUBLIC_API_BASE ??
  (typeof window !== "undefined" && window.location.hostname !== "localhost"
    ? "/api"
    : "http://localhost:8000");

export type PredictRequest = {
  patient_id?: string | null;
  age: number;
  sex: "M" | "F";
  chest_pain_type: "ASY" | "ATA" | "NAP" | "TA";
  max_hr: number;
  fasting_bs: 0 | 1;
  exercise_angina: "Y" | "N";
  st_slope: "Up" | "Flat" | "Down";
  resting_bp?: number | null;
  cholesterol?: number | null;
  resting_ecg?: "Normal" | "ST" | "LVH" | null;
  oldpeak?: number | null;
};

export type PredictResponse = {
  patient_id: string;
  timestamp: string;
  probability: number;
  classification: "HIGH" | "LOW";
  threshold: number;
  probabilities: [number, number];
};

export type HistoryEntry = {
  date: string;
  time: string;
  patient_id: string;
  age: number;
  sex: string;
  max_hr: number;
  fasting_bs: string;
  exercise_angina: string;
  chest_pain_type: string;
  st_slope: string;
  probability: number;
  classification: string;
  risk: string;
};

export type Stats = {
  total: number;
  high_risk: number;
  low_risk: number;
  high_risk_pct: number;
  today: number;
};

export type ModelInfo = {
  name: string;
  threshold: number;
  metrics: {
    accuracy: number;
    recall: number;
    roc_auc: number;
    cv_mean: number;
    cv_std: number;
  };
  alternatives: { name: string; accuracy: number; recall: number; roc_auc: number }[];
  features: string[];
};

async function request<T>(path: string, init?: RequestInit): Promise<T> {
  const res = await fetch(`${API_BASE}${path}`, {
    ...init,
    headers: { "Content-Type": "application/json", ...(init?.headers ?? {}) },
  });
  if (!res.ok) {
    throw new Error(`API ${res.status}: ${await res.text()}`);
  }
  return res.json();
}

export type EdaData = {
  age_dist: { bin: string; count: number; risk_rate: number }[];
  sex_dist: { sex: string; count: number; risk_rate: number }[];
  chest_pain_dist: { type: string; count: number; risk_rate: number }[];
  scatter: { Age: number; MaxHR: number; HeartDisease: number }[];
  total: number;
};

export const api = {
  predict: (body: PredictRequest) =>
    request<PredictResponse>("/predict", {
      method: "POST",
      body: JSON.stringify(body),
    }),
  history: () => request<HistoryEntry[]>("/history"),
  stats: () => request<Stats>("/stats"),
  modelInfo: () => request<ModelInfo>("/model-info"),
  eda: () => request<EdaData>("/eda"),
};