neuro-eeg-analysis / src /app /api /analysis.ts
Aysena's picture
Deploy Neuro EEG Analysis to Hugging Face Space (CPU Basic)
fa686c4
Raw
History Blame Contribute Delete
4.86 kB
import type { ModelType, PredictionClass } from "../context/AnalysisContext";
export interface ConfidenceScores {
Healthy: number;
MCI: number;
AD: number;
}
export interface FoldPrediction {
fold: number;
prediction: PredictionClass;
confidence: number;
confidence_scores: ConfidenceScores;
}
export interface AnalyzeResponse {
id: string;
file_name: string;
model: Exclude<ModelType, null>;
prediction: PredictionClass;
confidence: number;
confidence_scores: ConfidenceScores;
processed_at: string;
spectrogram_image: string | null;
scalogram_montage_image: string | null;
spectrogram_channels: (string | null)[];
scalogram_channels: (string | null)[];
channel_0_image: string | null;
channel_1_image: string | null;
mock: boolean;
fold_predictions: FoldPrediction[];
fold_vote_counts: Partial<Record<PredictionClass, number>>;
ensemble_folds: number;
ensemble_mode: string;
}
export interface TrialAnalysisResult {
id: string;
file_name: string;
trial_no: number | null;
prediction: PredictionClass;
confidence: number;
confidence_scores: ConfidenceScores;
spectrogram_image: string | null;
scalogram_montage_image: string | null;
spectrogram_channels: (string | null)[];
scalogram_channels: (string | null)[];
mock: boolean;
fold_predictions: FoldPrediction[];
fold_vote_counts: Partial<Record<PredictionClass, number>>;
ensemble_folds: number;
ensemble_mode: string;
}
export interface PatientAnalyzeResponse {
id: string;
patient_id: string;
model: Exclude<ModelType, null>;
prediction: PredictionClass;
confidence: number;
confidence_scores: ConfidenceScores;
vote_counts: Partial<Record<PredictionClass, number>>;
trial_count: number;
agreement_ratio: number;
processed_at: string;
trial_results: TrialAnalysisResult[];
mock: boolean;
}
const API_BASE = import.meta.env.VITE_API_URL ?? "";
export class AnalysisApiError extends Error {
constructor(
message: string,
public status?: number,
) {
super(message);
this.name = "AnalysisApiError";
}
}
export async function analyzeEeg(file: File, model: Exclude<ModelType, null>): Promise<AnalyzeResponse> {
const formData = new FormData();
formData.append("file", file);
formData.append("model", model);
const response = await fetch(`${API_BASE}/api/analyze`, {
method: "POST",
body: formData,
});
if (!response.ok) {
let detail = "Analysis request failed.";
try {
const body = await response.json();
if (typeof body.detail === "string") {
detail = body.detail;
} else if (Array.isArray(body.detail)) {
detail = body.detail.map((d: { msg?: string }) => d.msg).filter(Boolean).join(", ") || detail;
}
} catch {
if (response.status === 500) {
detail = "Server error — ensure the backend is running and USE_MOCK_INFERENCE=true in backend/.env";
}
}
throw new AnalysisApiError(detail, response.status);
}
return response.json();
}
export async function analyzePatientEeg(
files: File[],
model: Exclude<ModelType, null>,
): Promise<PatientAnalyzeResponse> {
const formData = new FormData();
files.forEach((file) => formData.append("files", file));
formData.append("model", model);
const response = await fetch(`${API_BASE}/api/analyze/patient`, {
method: "POST",
body: formData,
});
if (!response.ok) {
let detail = "Patient analysis request failed.";
try {
const body = await response.json();
if (typeof body.detail === "string") {
detail = body.detail;
} else if (Array.isArray(body.detail)) {
detail = body.detail.map((d: { msg?: string }) => d.msg).filter(Boolean).join(", ") || detail;
}
} catch {
if (response.status === 404) {
detail = "Patient endpoint not found — restart the backend (npm run dev:backend).";
} else if (response.status === 500) {
detail = "Server error — restart the backend and try again.";
}
}
throw new AnalysisApiError(detail, response.status);
}
return response.json();
}
export async function checkApiHealth(): Promise<boolean> {
try {
const response = await fetch(`${API_BASE}/api/health`);
return response.ok;
} catch {
return false;
}
}
export interface ModelStatusItem {
name: Exclude<ModelType, null>;
loaded: boolean;
weights_found: boolean;
weights_path: string;
}
export interface ModelsStatusResponse {
models: ModelStatusItem[];
use_mock_inference: boolean;
fusion_detail: Record<string, unknown> | null;
}
export async function fetchModelsStatus(): Promise<ModelsStatusResponse | null> {
try {
const response = await fetch(`${API_BASE}/api/models/status`);
if (!response.ok) return null;
return response.json();
} catch {
return null;
}
}