Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8" /> | |
| <meta name="viewport" content="width=device-width,initial-scale=1" /> | |
| <title>NTv3 — Next-Gen Foundation Models for Genomics</title> | |
| <meta name="description" content="NTv3 companion hub: PyTorch notebooks for inference, fine-tuning, interpretation, and sequence generation on NTv3 models hosted on Hugging Face." /> | |
| <link href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism-tomorrow.min.css" rel="stylesheet" /> | |
| <style> | |
| :root { | |
| --bg: #0b1020; | |
| --card: rgba(255, 255, 255, 0.06); | |
| --text: rgba(255, 255, 255, 0.92); | |
| --muted: rgba(255, 255, 255, 0.65); | |
| --link: #7dd3fc; | |
| --border: rgba(255, 255, 255, 0.12); | |
| --shadow: 0 10px 30px rgba(0,0,0,0.35); | |
| --radius: 18px; | |
| --mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; | |
| --sans: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, "Apple Color Emoji","Segoe UI Emoji"; | |
| } | |
| body { | |
| margin: 0; | |
| font-family: var(--sans); | |
| color: var(--text); | |
| background: | |
| radial-gradient(1200px 800px at 10% 10%, rgba(125, 211, 252, 0.12), transparent 60%), | |
| radial-gradient(1200px 800px at 90% 30%, rgba(167, 139, 250, 0.12), transparent 55%), | |
| var(--bg); | |
| min-height: 100vh; | |
| } | |
| .wrap { max-width: 980px; margin: 0 auto; padding: 44px 18px 56px; } | |
| .hero { | |
| display: grid; gap: 14px; | |
| padding: 26px 24px; | |
| border: 1px solid var(--border); | |
| background: var(--card); | |
| box-shadow: var(--shadow); | |
| border-radius: var(--radius); | |
| } | |
| h1 { font-size: 34px; margin: 0; letter-spacing: -0.02em; } | |
| p { margin: 0; color: var(--muted); line-height: 1.5; } | |
| .grid { | |
| margin-top: 18px; | |
| display: grid; | |
| grid-template-columns: repeat(12, 1fr); | |
| gap: 14px; | |
| } | |
| .card { | |
| grid-column: span 6; | |
| padding: 18px 18px; | |
| border: 1px solid var(--border); | |
| background: var(--card); | |
| border-radius: var(--radius); | |
| box-shadow: 0 6px 18px rgba(0,0,0,0.22); | |
| } | |
| .card-stack { | |
| grid-column: span 6; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 14px; | |
| } | |
| .card-stack .card { | |
| grid-column: span 1; | |
| margin: 0; | |
| } | |
| .card h2 { margin: 0 0 10px 0; font-size: 16px; letter-spacing: 0.01em; } | |
| .card ul { margin: 0; padding-left: 18px; color: var(--muted); } | |
| .card li { margin: 8px 0; } | |
| .card table { | |
| width: 100%; | |
| margin-top: 12px; | |
| border-collapse: collapse; | |
| font-size: 13px; | |
| } | |
| .card table th { | |
| text-align: left; | |
| padding: 10px 12px; | |
| border-bottom: 2px solid var(--border); | |
| color: var(--text); | |
| font-weight: 600; | |
| font-size: 12px; | |
| text-transform: uppercase; | |
| letter-spacing: 0.05em; | |
| } | |
| .card table td { | |
| padding: 10px 12px; | |
| border-bottom: 1px solid var(--border); | |
| color: var(--muted); | |
| } | |
| .card table tr:last-child td { | |
| border-bottom: none; | |
| } | |
| .card table tr:hover { | |
| background: rgba(255, 255, 255, 0.02); | |
| } | |
| .card table td .checkmark { | |
| color: #4ade80 ; | |
| } | |
| a { color: var(--link); text-decoration: none; } | |
| a:hover { text-decoration: underline; } | |
| .pillrow { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 8px; } | |
| .pill { | |
| font-size: 12px; | |
| padding: 6px 10px; | |
| border-radius: 999px; | |
| border: 1px solid var(--border); | |
| background: rgba(255,255,255,0.04); | |
| color: var(--muted); | |
| } | |
| .code { | |
| margin-top: 12px; | |
| padding: 16px 18px; | |
| border-radius: 14px; | |
| border: 1px solid var(--border); | |
| background: rgba(0,0,0,0.3); | |
| font-family: var(--mono); | |
| font-size: 13px; | |
| line-height: 1.6; | |
| overflow-x: auto; | |
| color: rgba(255,255,255,0.9); | |
| white-space: pre; | |
| } | |
| .code code { | |
| font-family: inherit; | |
| font-size: inherit; | |
| color: inherit; | |
| } | |
| /* Prism.js theme overrides to match dark theme */ | |
| .code pre[class*="language-"] { | |
| background: transparent; | |
| margin: 0; | |
| padding: 0; | |
| } | |
| .code code[class*="language-"] { | |
| background: transparent; | |
| } | |
| .summary { | |
| margin-top: 18px; | |
| padding: 24px; | |
| border: 1px solid var(--border); | |
| background: var(--card); | |
| border-radius: var(--radius); | |
| box-shadow: var(--shadow); | |
| } | |
| .summary h2 { | |
| margin: 0 0 16px 0; | |
| font-size: 18px; | |
| letter-spacing: 0.01em; | |
| } | |
| .summary p { | |
| margin: 0 0 14px 0; | |
| color: var(--muted); | |
| line-height: 1.7; | |
| } | |
| .summary p:last-child { | |
| margin-bottom: 0; | |
| } | |
| .why-ntv3 { | |
| margin-top: 18px; | |
| padding: 24px; | |
| border: 1px solid var(--border); | |
| background: var(--card); | |
| border-radius: var(--radius); | |
| box-shadow: var(--shadow); | |
| } | |
| .why-ntv3 h2 { | |
| margin: 0 0 16px 0; | |
| font-size: 18px; | |
| letter-spacing: 0.01em; | |
| } | |
| .why-ntv3 ul { | |
| margin: 0; | |
| padding-left: 0; | |
| list-style: none; | |
| color: var(--muted); | |
| } | |
| .why-ntv3 li { | |
| margin: 12px 0; | |
| padding-left: 0; | |
| line-height: 1.7; | |
| } | |
| .paper-summary { | |
| margin-top: 12px; | |
| padding: 24px; | |
| border: 1px solid var(--border); | |
| background: var(--card); | |
| border-radius: var(--radius); | |
| box-shadow: var(--shadow); | |
| } | |
| .paper-summary h2 { | |
| text-align: center; | |
| margin: 0 0 20px 0; | |
| } | |
| .paper-summary img { | |
| width: 100%; | |
| height: auto; | |
| display: block; | |
| border-radius: 12px; | |
| } | |
| .footer { margin-top: 22px; color: var(--muted); font-size: 13px; } | |
| /* Tab navigation styles */ | |
| .tabs { | |
| margin-top: 24px; | |
| display: flex; | |
| gap: 8px; | |
| border-bottom: 2px solid var(--border); | |
| overflow-x: auto; | |
| } | |
| .tab-button { | |
| padding: 12px 20px; | |
| background: transparent; | |
| border: none; | |
| border-bottom: 2px solid transparent; | |
| color: var(--muted); | |
| font-family: var(--sans); | |
| font-size: 14px; | |
| font-weight: 500; | |
| cursor: pointer; | |
| transition: all 0.2s ease; | |
| white-space: nowrap; | |
| margin-bottom: -2px; | |
| } | |
| .tab-button:hover { | |
| color: var(--text); | |
| background: rgba(255, 255, 255, 0.03); | |
| } | |
| .tab-button.active { | |
| color: var(--link); | |
| border-bottom-color: var(--link); | |
| } | |
| .tab-content { | |
| display: none; | |
| animation: fadeIn 0.3s ease; | |
| } | |
| .tab-content.active { | |
| display: block; | |
| } | |
| @keyframes fadeIn { | |
| from { opacity: 0; transform: translateY(8px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| @media (max-width: 860px) { | |
| .card { grid-column: span 12; } | |
| h1 { font-size: 28px; } | |
| .tab-button { | |
| padding: 10px 16px; | |
| font-size: 13px; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="wrap"> | |
| <div class="hero"> | |
| <h1>🧬 NTv3 — Next-Gen Foundation Models for Genomics</h1> | |
| <p> | |
| This Space is the companion hub for <strong>NTv3</strong> models: runnable notebooks for inference, fine-tuning, interpretation, and sequence generation. | |
| </p> | |
| <div class="pillrow"> | |
| <span class="pill">🤖 Foundation Models</span> | |
| <span class="pill">🧬 Long-context genomics</span> | |
| <span class="pill">🌍 Multi-species</span> | |
| <span class="pill">⚡ Inference • Fine-tune • Interpret • Generate</span> | |
| <span class="pill">📓 Torch notebooks</span> | |
| </div> | |
| </div> | |
| <!-- Tab Navigation --> | |
| <div class="tabs"> | |
| <button class="tab-button active" data-tab="home">🏠 Home</button> | |
| <button class="tab-button" data-tab="demo">🚀 Live Demo</button> | |
| </div> | |
| <!-- Home Tab (Content loaded from tabs/home.html) --> | |
| <div id="home" class="tab-content active"> | |
| <!-- Content will be loaded dynamically --> | |
| </div> | |
| <!-- Live Demo Tab (Content loaded from tabs/demo.html) --> | |
| <div id="demo" class="tab-content"> | |
| <!-- Content will be loaded dynamically --> | |
| </div> | |
| <!-- <div class="paper-summary"> | |
| <h2>📄 A foundational model for joint sequence-function multi-species modeling at scale for long-range genomic prediction</h2> | |
| <img src="assets/paper_summary.png" alt="NTv3 Paper Summary" /> | |
| </div> --> | |
| <p class="footer"> | |
| © instadeep-ai — NTv3 companion Space. | |
| </p> | |
| </div> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-core.min.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/autoloader/prism-autoloader.min.js"></script> | |
| <script> | |
| // Tab content mapping | |
| const tabFiles = { | |
| 'home': 'tabs/home.html', | |
| 'demo': 'tabs/demo.html', | |
| 'functional_tracks': 'tabs/functional_tracks.html', | |
| }; | |
| // Cache for loaded tab content | |
| const tabCache = {}; | |
| // Function to load tab content | |
| async function loadTabContent(tabId) { | |
| // Return cached content if available | |
| if (tabCache[tabId]) { | |
| return tabCache[tabId]; | |
| } | |
| // Load content from file | |
| const filePath = tabFiles[tabId]; | |
| if (!filePath) { | |
| console.error(`No file path defined for tab: ${tabId}`); | |
| return ''; | |
| } | |
| try { | |
| const response = await fetch(filePath); | |
| if (!response.ok) { | |
| throw new Error(`Failed to load ${filePath}: ${response.statusText}`); | |
| } | |
| const content = await response.text(); | |
| tabCache[tabId] = content; | |
| return content; | |
| } catch (error) { | |
| console.error(`Error loading tab content for ${tabId}:`, error); | |
| return `<div class="summary"><p>Error loading content. Please refresh the page.</p></div>`; | |
| } | |
| } | |
| // Function to show a tab | |
| async function showTab(tabId) { | |
| const tabContent = document.getElementById(tabId); | |
| if (!tabContent) { | |
| console.error(`Tab element not found: ${tabId}`); | |
| return; | |
| } | |
| // Load content if not already loaded | |
| if (!tabContent.dataset.loaded) { | |
| tabContent.innerHTML = await loadTabContent(tabId); | |
| tabContent.dataset.loaded = 'true'; | |
| // Re-run Prism.js syntax highlighting for code blocks in the loaded content | |
| if (typeof Prism !== 'undefined') { | |
| // Find all code blocks in the loaded content and highlight them | |
| const codeBlocks = tabContent.querySelectorAll('code[class*="language-"]'); | |
| codeBlocks.forEach(block => { | |
| Prism.highlightElement(block); | |
| }); | |
| } | |
| } | |
| } | |
| // Tab switching functionality | |
| document.addEventListener('DOMContentLoaded', function() { | |
| const tabButtons = document.querySelectorAll('.tab-button'); | |
| const tabContents = document.querySelectorAll('.tab-content'); | |
| // Load the default active tab (home) | |
| const activeTab = document.querySelector('.tab-content.active'); | |
| if (activeTab) { | |
| showTab(activeTab.id); | |
| } | |
| tabButtons.forEach(button => { | |
| button.addEventListener('click', async () => { | |
| const targetTab = button.getAttribute('data-tab'); | |
| // Remove active class from all buttons and contents | |
| tabButtons.forEach(btn => btn.classList.remove('active')); | |
| tabContents.forEach(content => content.classList.remove('active')); | |
| // Add active class to clicked button and corresponding content | |
| button.classList.add('active'); | |
| const tabElement = document.getElementById(targetTab); | |
| tabElement.classList.add('active'); | |
| // Load and show the tab content | |
| await showTab(targetTab); | |
| }); | |
| }); | |
| }); | |
| </script> | |
| </body> | |
| </html> | |