// Upload and Prediction JavaScript // Image preview functionality function setupImagePreview(inputId, previewId, placeholderId) { const input = document.getElementById(inputId); const preview = document.getElementById(previewId); const placeholder = input.parentElement.querySelector('.upload-placeholder'); if (input) { input.addEventListener('change', function(e) { const file = e.target.files[0]; if (file) { const reader = new FileReader(); reader.onload = function(e) { preview.src = e.target.result; preview.style.display = 'block'; if (placeholder) placeholder.style.display = 'none'; }; reader.readAsDataURL(file); } }); } } // Setup previews based on mode if (mode === 'multimodal') { setupImagePreview('fundusImage', 'fundusPreview'); setupImagePreview('octImage', 'octPreview'); } else if (mode === 'fundus') { setupImagePreview('fundusImage', 'fundusPreview'); } else if (mode === 'oct') { setupImagePreview('octImage', 'octPreview'); } // Form submission const form = document.getElementById('uploadForm'); const analyzeBtn = document.getElementById('analyzeBtn'); const btnText = document.getElementById('btnText'); const btnLoader = document.getElementById('btnLoader'); const errorMessage = document.getElementById('errorMessage'); const resultsSection = document.getElementById('resultsSection'); form.addEventListener('submit', async function(e) { e.preventDefault(); // Show loading state btnText.style.display = 'none'; btnLoader.style.display = 'inline-block'; analyzeBtn.disabled = true; errorMessage.style.display = 'none'; resultsSection.style.display = 'none'; try { const formData = new FormData(form); const endpoint = `/predict/${mode}`; const response = await fetch(endpoint, { method: 'POST', body: formData }); if (!response.ok) { throw new Error('Prediction failed'); } const result = await response.json(); // Display results displayResults(result); } catch (error) { console.error('Error:', error); errorMessage.textContent = 'An error occurred during analysis. Please try again.'; errorMessage.style.display = 'block'; } finally { // Reset button state btnText.style.display = 'inline'; btnLoader.style.display = 'none'; analyzeBtn.disabled = false; } }); function displayResults(result) { let html = ''; if (mode === 'fundus') { html = generateFundusResults(result); } else if (mode === 'oct') { html = generateOCTResults(result); } else if (mode === 'multimodal') { html = generateMultimodalResults(result); } resultsSection.innerHTML = html; resultsSection.style.display = 'block'; // Scroll to results resultsSection.scrollIntoView({ behavior: 'smooth', block: 'start' }); } function generateFundusResults(result) { const isGlaucoma = result.prediction === 'GON+'; const headerClass = isGlaucoma ? 'warning' : 'success'; return `
${result.prediction}
Confidence: ${(result.confidence * 100).toFixed(1)}%

Original Image

Original

Grad-CAM Visualization

${result.gradcam_image ? `Grad-CAM` : '

Visualization not available

' }
vCDR (Cup-to-Disc Ratio)
${result.vcdr.toFixed(2)}
Prediction Confidence
${(result.confidence * 100).toFixed(1)}%
Clinical Interpretation:
${result.interpretation}
`; } function generateOCTResults(result) { const isNormal = result.prediction === 'NO'; const headerClass = isNormal ? 'success' : 'warning'; let top3HTML = result.top3.map((item, index) => `
${index + 1}. ${item.class}
${(item.probability * 100).toFixed(1)}%
` ).join(''); return `
${result.prediction}
Confidence: ${(result.confidence * 100).toFixed(1)}%

Original Image

Original

Grad-CAM Visualization

${result.gradcam_image ? `Grad-CAM` : '

Visualization not available

' }

Top 3 Predictions

${top3HTML}
Clinical Interpretation:
${result.interpretation}
`; } function generateMultimodalResults(result) { const isGlaucoma = result.prediction === 'GLAUCOMA'; const headerClass = isGlaucoma ? 'warning' : 'success'; return `
${result.prediction}
Confidence: ${(result.confidence * 100).toFixed(1)}%

Fundus Image

Fundus
Fundus Grad-CAM
${result.fundus_gradcam ? `Fundus Grad-CAM` : '

Visualization not available

' }

OCT Image

OCT
OCT Grad-CAM
${result.oct_gradcam ? `OCT Grad-CAM` : '

Visualization not available

' }
vCDR (Cup-to-Disc Ratio)
${result.vcdr.toFixed(2)}
RNFL Thickness
${result.rnfl.toFixed(1)} μm
Prediction Confidence
${(result.confidence * 100).toFixed(1)}%
Analysis Type
Multimodal
Clinical Interpretation:
${result.interpretation}
`; }