Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Genomic Data Analysis Platform</title> | |
| <link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet"> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| .upload-area { | |
| border: 2px dashed #4f46e5; | |
| transition: all 0.3s ease; | |
| } | |
| .upload-area:hover { | |
| background-color: #f0f9ff; | |
| border-color: #3b82f6; | |
| } | |
| .file-item { | |
| transition: all 0.2s ease; | |
| } | |
| .file-item:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); | |
| } | |
| .progress-bar { | |
| transition: width 0.5s ease; | |
| } | |
| .pulse { | |
| animation: pulse 2s infinite; | |
| } | |
| @keyframes pulse { | |
| 0% { opacity: 1; } | |
| 50% { opacity: 0.5; } | |
| 100% { opacity: 1; } | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gradient-to-br from-blue-50 to-indigo-100 min-h-screen"> | |
| <div class="container mx-auto px-4 py-8"> | |
| <!-- Header --> | |
| <header class="text-center mb-12"> | |
| <h1 class="text-4xl md:text-5xl font-bold text-gray-800 mb-4"> | |
| <span class="bg-clip-text text-transparent bg-gradient-to-r from-blue-600 to-indigo-600"> | |
| Genomic Data Analysis Platform | |
| </span> | |
| </h1> | |
| <p class="text-lg text-gray-600 max-w-3xl mx-auto"> | |
| Upload genomic data files and perform semantic analysis to find matching research from NIH and Semantic Scholar. Generate comprehensive AI-powered reports. | |
| </p> | |
| </header> | |
| <!-- Main Content --> | |
| <div class="grid grid-cols-1 lg:grid-cols-2 gap-8"> | |
| <!-- Upload Section --> | |
| <div class="bg-white rounded-2xl shadow-xl p-6"> | |
| <h2 class="text-2xl font-bold text-gray-800 mb-6 flex items-center"> | |
| <i class="fas fa-cloud-upload-alt text-indigo-600 mr-3"></i> | |
| Upload Files | |
| </h2> | |
| <!-- File Upload Area --> | |
| <div id="uploadArea" class="upload-area rounded-xl p-8 text-center cursor-pointer mb-6"> | |
| <i class="fas fa-file-upload text-4xl text-indigo-500 mb-4"></i> | |
| <h3 class="text-xl font-semibold text-gray-700 mb-2">Drag & Drop Files</h3> | |
| <p class="text-gray-500 mb-4">Supports: txt, csv, gz, vcf, json</p> | |
| <button id="browseBtn" class="bg-indigo-600 hover:bg-indigo-700 text-white font-medium py-2 px-6 rounded-lg transition duration-300"> | |
| Browse Files | |
| </button> | |
| <input type="file" id="fileInput" multiple class="hidden" accept=".txt,.csv,.gz,.vcf,.json"> | |
| </div> | |
| <!-- File List --> | |
| <div id="fileList" class="space-y-3 mb-6"> | |
| <!-- Files will be listed here --> | |
| </div> | |
| <!-- Knowledge JSON Toggle --> | |
| <div class="flex items-center justify-between bg-blue-50 rounded-lg p-4 mb-6"> | |
| <div> | |
| <h3 class="font-medium text-gray-800">Include Knowledge JSON</h3> | |
| <p class="text-sm text-gray-600">Optional: Upload domain-specific knowledge base</p> | |
| </div> | |
| <div class="relative inline-block w-12 mr-2 align-middle select-none"> | |
| <input type="checkbox" id="knowledgeToggle" class="sr-only"> | |
| <label for="knowledgeToggle" class="block h-6 w-12 rounded-full bg-gray-300 cursor-pointer transition duration-300 ease-in-out"> | |
| <span class="block h-4 w-4 mt-1 ml-1 rounded-full bg-white shadow transform transition duration-300 ease-in-out"></span> | |
| </label> | |
| </div> | |
| </div> | |
| <!-- Analysis Button --> | |
| <button id="analyzeBtn" class="w-full bg-gradient-to-r from-indigo-600 to-purple-600 hover:from-indigo-700 hover:to-purple-700 text-white font-bold py-4 px-6 rounded-xl shadow-lg transition duration-300 transform hover:scale-[1.02] disabled:opacity-50 disabled:cursor-not-allowed"> | |
| <i class="fas fa-dna mr-2"></i> | |
| Start Genomic Analysis | |
| </button> | |
| </div> | |
| <!-- Results Section --> | |
| <div class="bg-white rounded-2xl shadow-xl p-6"> | |
| <h2 class="text-2xl font-bold text-gray-800 mb-6 flex items-center"> | |
| <i class="fas fa-chart-bar text-indigo-600 mr-3"></i> | |
| Analysis Results | |
| </h2> | |
| <!-- Status Indicators --> | |
| <div id="statusContainer" class="space-y-4 mb-6"> | |
| <div id="uploadStatus" class="flex items-center p-3 bg-gray-50 rounded-lg"> | |
| <div class="w-3 h-3 rounded-full bg-gray-400 mr-3"></div> | |
| <span class="text-gray-600">Upload genomic data files</span> | |
| </div> | |
| <div id="processStatus" class="flex items-center p-3 bg-gray-50 rounded-lg"> | |
| <div class="w-3 h-3 rounded-full bg-gray-400 mr-3"></div> | |
| <span class="text-gray-600">Processing genomic data</span> | |
| </div> | |
| <div id="researchStatus" class="flex items-center p-3 bg-gray-50 rounded-lg"> | |
| <div class="w-3 h-3 rounded-full bg-gray-400 mr-3"></div> | |
| <span class="text-gray-600">Finding matching research</span> | |
| </div> | |
| <div id="reportStatus" class="flex items-center p-3 bg-gray-50 rounded-lg"> | |
| <div class="w-3 h-3 rounded-full bg-gray-400 mr-3"></div> | |
| <span class="text-gray-600">Generating comprehensive report</span> | |
| </div> | |
| </div> | |
| <!-- Progress Bar --> | |
| <div class="mb-6"> | |
| <div class="flex justify-between text-sm text-gray-600 mb-1"> | |
| <span>Analysis Progress</span> | |
| <span id="progressText">0%</span> | |
| </div> | |
| <div class="h-3 bg-gray-200 rounded-full overflow-hidden"> | |
| <div id="progressBar" class="h-full bg-gradient-to-r from-blue-500 to-indigo-600 rounded-full progress-bar" style="width: 0%"></div> | |
| </div> | |
| </div> | |
| <!-- Results Summary --> | |
| <div id="resultsSummary" class="hidden"> | |
| <div class="grid grid-cols-2 gap-4 mb-6"> | |
| <div class="bg-blue-50 p-4 rounded-lg"> | |
| <div class="text-2xl font-bold text-indigo-700">24</div> | |
| <div class="text-sm text-gray-600">Research Papers Found</div> | |
| </div> | |
| <div class="bg-green-50 p-4 rounded-lg"> | |
| <div class="text-2xl font-bold text-green-700">8</div> | |
| <div class="text-sm text-gray-600">Highly Relevant</div> | |
| </div> | |
| </div> | |
| <div class="mb-6"> | |
| <h3 class="font-bold text-gray-800 mb-3">Top Research Matches</h3> | |
| <div class="space-y-3"> | |
| <div class="p-3 bg-gray-50 rounded-lg"> | |
| <div class="font-medium text-gray-800">Genome-wide association study of...</div> | |
| <div class="text-sm text-gray-600">NIH Database • 2023</div> | |
| </div> | |
| <div class="p-3 bg-gray-50 rounded-lg"> | |
| <div class="font-medium text-gray-800">Semantic analysis of genetic variants...</div> | |
| <div class="text-sm text-gray-600">Semantic Scholar • 2022</div> | |
| </div> | |
| </div> | |
| </div> | |
| <button id="downloadBtn" class="w-full bg-gradient-to-r from-green-500 to-emerald-600 hover:from-green-600 hover:to-emerald-700 text-white font-bold py-3 px-6 rounded-xl shadow-lg transition duration-300 flex items-center justify-center"> | |
| <i class="fas fa-download mr-2"></i> | |
| Download DOCX Report | |
| </button> | |
| </div> | |
| <!-- Placeholder when no results --> | |
| <div id="noResults" class="text-center py-12"> | |
| <i class="fas fa-microscope text-5xl text-gray-300 mb-4"></i> | |
| <p class="text-gray-500">Upload files and start analysis to see results</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Features Section --> | |
| <div class="mt-16"> | |
| <h2 class="text-3xl font-bold text-center text-gray-800 mb-12">How It Works</h2> | |
| <div class="grid grid-cols-1 md:grid-cols-3 gap-8"> | |
| <div class="bg-white p-6 rounded-2xl shadow-lg text-center"> | |
| <div class="w-16 h-16 bg-blue-100 rounded-full flex items-center justify-center mx-auto mb-4"> | |
| <i class="fas fa-file-upload text-blue-600 text-2xl"></i> | |
| </div> | |
| <h3 class="text-xl font-bold text-gray-800 mb-2">Upload Data</h3> | |
| <p class="text-gray-600">Upload genomic files in various formats including VCF, CSV, and TXT</p> | |
| </div> | |
| <div class="bg-white p-6 rounded-2xl shadow-lg text-center"> | |
| <div class="w-16 h-16 bg-indigo-100 rounded-full flex items-center justify-center mx-auto mb-4"> | |
| <i class="fas fa-brain text-indigo-600 text-2xl"></i> | |
| </div> | |
| <h3 class="text-xl font-bold text-gray-800 mb-2">AI Analysis</h3> | |
| <p class="text-gray-600">Semantic analysis using advanced AI to interpret genomic data</p> | |
| </div> | |
| <div class="bg-white p-6 rounded-2xl shadow-lg text-center"> | |
| <div class="w-16 h-16 bg-green-100 rounded-full flex items-center justify-center mx-auto mb-4"> | |
| <i class="fas fa-file-medical text-green-600 text-2xl"></i> | |
| </div> | |
| <h3 class="text-xl font-bold text-gray-800 mb-2">Research Matching</h3> | |
| <p class="text-gray-600">Find relevant research from NIH and Semantic Scholar databases</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| document.addEventListener('DOMContentLoaded', function() { | |
| // Elements | |
| const uploadArea = document.getElementById('uploadArea'); | |
| const fileInput = document.getElementById('fileInput'); | |
| const browseBtn = document.getElementById('browseBtn'); | |
| const fileList = document.getElementById('fileList'); | |
| const analyzeBtn = document.getElementById('analyzeBtn'); | |
| const downloadBtn = document.getElementById('downloadBtn'); | |
| const knowledgeToggle = document.getElementById('knowledgeToggle'); | |
| const progressBar = document.getElementById('progressBar'); | |
| const progressText = document.getElementById('progressText'); | |
| const resultsSummary = document.getElementById('resultsSummary'); | |
| const noResults = document.getElementById('noResults'); | |
| const statusContainer = document.getElementById('statusContainer'); | |
| // Status indicators | |
| const uploadStatus = document.getElementById('uploadStatus').querySelector('div'); | |
| const processStatus = document.getElementById('processStatus').querySelector('div'); | |
| const researchStatus = document.getElementById('researchStatus').querySelector('div'); | |
| const reportStatus = document.getElementById('reportStatus').querySelector('div'); | |
| // File storage | |
| let uploadedFiles = []; | |
| // Event Listeners | |
| browseBtn.addEventListener('click', () => fileInput.click()); | |
| fileInput.addEventListener('change', handleFileSelect); | |
| uploadArea.addEventListener('dragover', handleDragOver); | |
| uploadArea.addEventListener('drop', handleDrop); | |
| analyzeBtn.addEventListener('click', startAnalysis); | |
| downloadBtn.addEventListener('click', downloadReport); | |
| // Functions | |
| function handleDragOver(e) { | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| uploadArea.classList.add('bg-blue-50'); | |
| } | |
| function handleDrop(e) { | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| uploadArea.classList.remove('bg-blue-50'); | |
| const files = e.dataTransfer.files; | |
| handleFiles(files); | |
| } | |
| function handleFileSelect(e) { | |
| const files = e.target.files; | |
| handleFiles(files); | |
| } | |
| function handleFiles(files) { | |
| for (let i = 0; i < files.length; i++) { | |
| const file = files[i]; | |
| if (validateFile(file)) { | |
| uploadedFiles.push(file); | |
| addFileToList(file); | |
| } | |
| } | |
| updateAnalyzeButton(); | |
| } | |
| function validateFile(file) { | |
| const validExtensions = ['.txt', '.csv', '.gz', '.vcf', '.json']; | |
| const extension = '.' + file.name.split('.').pop().toLowerCase(); | |
| return validExtensions.includes(extension); | |
| } | |
| function addFileToList(file) { | |
| const fileItem = document.createElement('div'); | |
| fileItem.className = 'file-item flex items-center justify-between p-3 bg-gray-50 rounded-lg'; | |
| const fileInfo = document.createElement('div'); | |
| fileInfo.className = 'flex items-center'; | |
| const fileIcon = document.createElement('i'); | |
| fileIcon.className = getFileIcon(file.name); | |
| fileIcon.classList.add('text-indigo-500', 'mr-3'); | |
| const fileName = document.createElement('span'); | |
| fileName.className = 'text-gray-700 truncate max-w-xs'; | |
| fileName.textContent = file.name; | |
| fileInfo.appendChild(fileIcon); | |
| fileInfo.appendChild(fileName); | |
| const fileSize = document.createElement('span'); | |
| fileSize.className = 'text-sm text-gray-500 ml-2'; | |
| fileSize.textContent = formatFileSize(file.size); | |
| const removeBtn = document.createElement('button'); | |
| removeBtn.className = 'text-red-500 hover:text-red-700 ml-2'; | |
| removeBtn.innerHTML = '<i class="fas fa-times"></i>'; | |
| removeBtn.addEventListener('click', () => { | |
| const index = uploadedFiles.indexOf(file); | |
| if (index > -1) { | |
| uploadedFiles.splice(index, 1); | |
| fileItem.remove(); | |
| updateAnalyzeButton(); | |
| } | |
| }); | |
| fileItem.appendChild(fileInfo); | |
| fileItem.appendChild(fileSize); | |
| fileItem.appendChild(removeBtn); | |
| fileList.appendChild(fileItem); | |
| } | |
| function getFileIcon(filename) { | |
| const extension = filename.split('.').pop().toLowerCase(); | |
| switch (extension) { | |
| case 'vcf': return 'fas fa-dna'; | |
| case 'csv': return 'fas fa-table'; | |
| case 'txt': return 'fas fa-file-alt'; | |
| case 'gz': return 'fas fa-file-archive'; | |
| case 'json': return 'fas fa-code'; | |
| default: return 'fas fa-file'; | |
| } | |
| } | |
| function formatFileSize(bytes) { | |
| if (bytes === 0) return '0 Bytes'; | |
| const k = 1024; | |
| const sizes = ['Bytes', 'KB', 'MB', 'GB']; | |
| const i = Math.floor(Math.log(bytes) / Math.log(k)); | |
| return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; | |
| } | |
| function updateAnalyzeButton() { | |
| const hasGenomicFiles = uploadedFiles.some(file => { | |
| const ext = file.name.split('.').pop().toLowerCase(); | |
| return ['vcf', 'txt', 'csv', 'gz'].includes(ext); | |
| }); | |
| analyzeBtn.disabled = !hasGenomicFiles || uploadedFiles.length === 0; | |
| } | |
| function startAnalysis() { | |
| if (uploadedFiles.length === 0) return; | |
| // Reset UI | |
| resetStatusIndicators(); | |
| resultsSummary.classList.add('hidden'); | |
| noResults.classList.add('hidden'); | |
| // Show processing | |
| uploadArea.classList.add('opacity-50', 'pointer-events-none'); | |
| analyzeBtn.disabled = true; | |
| analyzeBtn.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i> Analyzing...'; | |
| // Simulate analysis process | |
| simulateAnalysis(); | |
| } | |
| function resetStatusIndicators() { | |
| // Reset all status indicators | |
| const indicators = statusContainer.querySelectorAll('div > div:first-child'); | |
| indicators.forEach(indicator => { | |
| indicator.className = 'w-3 h-3 rounded-full bg-gray-400 mr-3'; | |
| }); | |
| // Reset progress | |
| progressBar.style.width = '0%'; | |
| progressText.textContent = '0%'; | |
| } | |
| function simulateAnalysis() { | |
| let progress = 0; | |
| const steps = [ | |
| { duration: 1000, status: 'uploadStatus' }, | |
| { duration: 2000, status: 'processStatus' }, | |
| { duration: 2500, status: 'researchStatus' }, | |
| { duration: 1500, status: 'reportStatus' } | |
| ]; | |
| function updateStep(stepIndex) { | |
| if (stepIndex >= steps.length) { | |
| // Analysis complete | |
| finishAnalysis(); | |
| return; | |
| } | |
| const step = steps[stepIndex]; | |
| const statusElement = document.getElementById(step.status).querySelector('div'); | |
| statusElement.className = 'w-3 h-3 rounded-full bg-blue-500 mr-3 pulse'; | |
| const interval = setInterval(() => { | |
| if (progress < ((stepIndex + 1) / steps.length) * 100) { | |
| progress += 2; | |
| progressBar.style.width = `${progress}%`; | |
| progressText.textContent = `${Math.min(progress, 100)}%`; | |
| } else { | |
| clearInterval(interval); | |
| statusElement.className = 'w-3 h-3 rounded-full bg-green-500 mr-3'; | |
| setTimeout(() => updateStep(stepIndex + 1), 300); | |
| } | |
| }, step.duration / 50); | |
| } | |
| updateStep(0); | |
| } | |
| function finishAnalysis() { | |
| uploadArea.classList.remove('opacity-50', 'pointer-events-none'); | |
| analyzeBtn.disabled = false; | |
| analyzeBtn.innerHTML = '<i class="fas fa-dna mr-2"></i> Start Genomic Analysis'; | |
| // Show results | |
| setTimeout(() => { | |
| resultsSummary.classList.remove('hidden'); | |
| noResults.classList.add('hidden'); | |
| }, 500); | |
| } | |
| function downloadReport() { | |
| // Simulate download | |
| downloadBtn.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i> Preparing...'; | |
| setTimeout(() => { | |
| downloadBtn.innerHTML = '<i class="fas fa-download mr-2"></i> Download DOCX Report'; | |
| // In a real app, this would trigger the actual download | |
| alert('Report download would start now. In a real application, this would download the generated DOCX file.'); | |
| }, 1500); | |
| } | |
| // Initialize | |
| updateAnalyzeButton(); | |
| }); | |
| </script> | |
| </body> | |
| </html> |