import React, { useState, useCallback, useEffect } from "react"; import { useDropzone } from "react-dropzone"; import { apiClient, SpectrumData, ComparisonResult, ModelInfo, PredictionResult, } from "../apiClient"; import SpectrumChart from "./SpectrumChart"; import ResultsDisplay from "./ResultsDisplay"; // We'll reuse parts of this component's display logic import "../static/style.css"; interface ModelComparisonProps { modality: "raman" | "ftir"; } const ModelComparison: React.FC = ({ modality }) => { const [spectrum, setSpectrum] = useState(null); const [comparisonResult, setComparisonResult] = useState(null); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [availableModels, setAvailableModels] = useState([]); const [selectedModels, setSelectedModels] = useState([]); useEffect(() => { const fetchModels = async () => { try { const models = await apiClient.getModels(); const available = models.filter((m) => m.available); setAvailableModels(available); // Default to selecting the first two models for comparison setSelectedModels(available.slice(0, 2).map((m) => m.name)); } catch (err) { setError("Failed to fetch available models."); } }; fetchModels(); }, []); const onDrop = useCallback(async (acceptedFiles: File[]) => { if (acceptedFiles.length === 0) return; const file = acceptedFiles[0]; setError(null); setLoading(true); try { const uploadedSpectrum = await apiClient.uploadSpectrum(file); setSpectrum(uploadedSpectrum); setComparisonResult(null); // Clear previous results on new upload } catch (err) { setError(err instanceof Error ? err.message : "Failed to upload file"); } finally { setLoading(false); } }, []); const handleToggleModel = (modelName: string) => { setSelectedModels((prev) => prev.includes(modelName) ? prev.filter((m) => m !== modelName) : [...prev, modelName] ); }; const handleCompare = async () => { if (!spectrum) { setError("Please upload a spectrum file first."); return; } if (selectedModels.length < 2) { setError("Please select at least two models to compare."); return; } setError(null); setLoading(true); try { const result = await apiClient.compareModels({ spectrum: spectrum, modality: modality, model_names: selectedModels, include_provenance: true, // Add this property }); setComparisonResult(result); } catch (err) { setError( err instanceof Error ? err.message : "Comparison analysis failed." ); } finally { setLoading(false); } }; const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop }); return (
{/* --- LEFT COLUMN (CONTROLS) --- */}

1. Upload Spectrum

📤

{isDragActive ? "Drop file to upload" : "Drag & drop, or click to select"}

{spectrum && (

Loaded: {spectrum.filename || "Unknown"}

)}

2. Select Models to Compare

{availableModels.map((model) => ( ))}

3. Run Comparison

{error && (
{error}
)}
{/* --- RIGHT COLUMN (RESULTS) --- */}

Comparison Results

{loading && (
Running comparison analysis...
)} {comparisonResult ? (

Best Performing Model

{comparisonResult.model_results && (

{ Object.entries(comparisonResult.model_results).reduce( (best, [modelName, res]) => res.confidence > best.confidence ? { modelName, confidence: res.confidence } : best, { modelName: "Unknown", confidence: 0 } ).modelName } {" "} with a confidence of{" "} {( Object.entries(comparisonResult.model_results).reduce( (best, [_, res]) => res.confidence > best ? res.confidence : best, 0 ) * 100 ).toFixed(1)} % .

)}
{comparisonResult.model_results && Object.entries(comparisonResult.model_results).map( ([modelName, res]) => (
{modelName} {(res.confidence * 100).toFixed(1)}%
) )}
) : ( !loading && (

Upload a spectrum and select models to see comparison results.

) )}
); }; export default ModelComparison;