Spaces:
Running on Zero
Running on Zero
| """Hero / landing page — NV-Generate masthead + three equal-height datasheet cards.""" | |
| from __future__ import annotations | |
| import gradio as gr | |
| # SVG modality glyphs — each is a recognizable anatomical silhouette of the modality. | |
| # CT: axial body cross-section with spine and ribs. | |
| # MR: a k-space spiral trajectory. | |
| # MR-Brain: an axial brain outline with hemispheres. | |
| SVG_CT = """ | |
| <svg viewBox="0 0 80 80" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"> | |
| <!-- Axial body cross-section silhouette --> | |
| <ellipse cx="40" cy="44" rx="30" ry="24" fill="none" stroke="currentColor" stroke-width="1.2"/> | |
| <!-- Lungs (left & right) --> | |
| <path d="M22 38 Q20 50 26 56 Q32 54 33 44 Q33 36 28 34 Q24 34 22 38 Z" | |
| fill="none" stroke="currentColor" stroke-width="0.9" stroke-opacity="0.7"/> | |
| <path d="M58 38 Q60 50 54 56 Q48 54 47 44 Q47 36 52 34 Q56 34 58 38 Z" | |
| fill="none" stroke="currentColor" stroke-width="0.9" stroke-opacity="0.7"/> | |
| <!-- Spine vertebra --> | |
| <ellipse cx="40" cy="56" rx="5" ry="4" fill="none" stroke="currentColor" stroke-width="0.9"/> | |
| <circle cx="40" cy="56" r="1.5" fill="currentColor" opacity="0.6"/> | |
| <!-- Calibration ticks --> | |
| <line x1="4" y1="44" x2="10" y2="44" stroke="currentColor" stroke-width="0.6" stroke-opacity="0.6"/> | |
| <line x1="70" y1="44" x2="76" y2="44" stroke="currentColor" stroke-width="0.6" stroke-opacity="0.6"/> | |
| <line x1="40" y1="14" x2="40" y2="20" stroke="currentColor" stroke-width="0.6" stroke-opacity="0.6"/> | |
| <line x1="40" y1="68" x2="40" y2="74" stroke="currentColor" stroke-width="0.6" stroke-opacity="0.6"/> | |
| </svg> | |
| """ | |
| SVG_MR = """ | |
| <svg viewBox="0 0 80 80" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"> | |
| <!-- k-space spiral trajectory: concentric arcs forming an inward spiral --> | |
| <circle cx="40" cy="40" r="6" fill="none" stroke="currentColor" stroke-width="1" stroke-opacity="1.0"/> | |
| <circle cx="40" cy="40" r="12" fill="none" stroke="currentColor" stroke-width="1" stroke-opacity="0.8" stroke-dasharray="6 1"/> | |
| <circle cx="40" cy="40" r="18" fill="none" stroke="currentColor" stroke-width="1" stroke-opacity="0.6" stroke-dasharray="8 2"/> | |
| <circle cx="40" cy="40" r="24" fill="none" stroke="currentColor" stroke-width="1" stroke-opacity="0.4" stroke-dasharray="10 3"/> | |
| <circle cx="40" cy="40" r="30" fill="none" stroke="currentColor" stroke-width="0.8" stroke-opacity="0.25" stroke-dasharray="12 4"/> | |
| <!-- Radial sampling line from center outward --> | |
| <line x1="40" y1="40" x2="62" y2="22" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/> | |
| <circle cx="40" cy="40" r="1.8" fill="currentColor"/> | |
| <circle cx="62" cy="22" r="1.5" fill="currentColor" opacity="0.6"/> | |
| </svg> | |
| """ | |
| SVG_MRB = """ | |
| <svg viewBox="0 0 80 80" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"> | |
| <!-- Axial brain silhouette with hemispheres --> | |
| <path d="M40 14 | |
| C28 14 18 22 16 34 | |
| C14 44 18 56 30 62 | |
| L33 62 | |
| C24 56 22 48 24 38 | |
| C26 28 32 22 40 22 | |
| C48 22 54 28 56 38 | |
| C58 48 56 56 47 62 | |
| L50 62 | |
| C62 56 66 44 64 34 | |
| C62 22 52 14 40 14 Z" | |
| fill="none" stroke="currentColor" stroke-width="1.2"/> | |
| <!-- Midline (longitudinal fissure) --> | |
| <line x1="40" y1="16" x2="40" y2="62" stroke="currentColor" stroke-width="0.9" stroke-opacity="0.55"/> | |
| <!-- Gyrus / sulcus hints, left & right --> | |
| <path d="M28 28 Q34 32 32 38" fill="none" stroke="currentColor" stroke-width="0.6" stroke-opacity="0.5"/> | |
| <path d="M52 28 Q46 32 48 38" fill="none" stroke="currentColor" stroke-width="0.6" stroke-opacity="0.5"/> | |
| <path d="M28 44 Q34 48 32 54" fill="none" stroke="currentColor" stroke-width="0.6" stroke-opacity="0.5"/> | |
| <path d="M52 44 Q46 48 48 54" fill="none" stroke="currentColor" stroke-width="0.6" stroke-opacity="0.5"/> | |
| </svg> | |
| """ | |
| # Each card has exactly 5 spec rows, each value short enough to render on one line. | |
| CARDS = [ | |
| { | |
| "key": "ct", | |
| "index": "01", | |
| "title": "NV-Generate · CT", | |
| "subtitle": "Whole-body synthetic CT with paired anatomy masks.", | |
| "icon": SVG_CT, | |
| "icon_caption": "Body region · paired anatomy", | |
| # Consistent category: USE CASES across all three cards. | |
| "uses": ["Segmentation data", "Pathology augmentation", "Privacy-preserving sharing"], | |
| "license": "NVIDIA Open Model", | |
| "license_tone": "ok", | |
| "spec": [ | |
| ("MODALITY", "Computed Tomography"), | |
| ("ARCHITECTURE", "MAISI-v2 · Rectified Flow"), | |
| ("MAX VOLUME", "512 × 512 × 768 vox"), | |
| ("SEGMENTATION", "132 classes · paired"), | |
| ("LICENSE", "NVIDIA Open Model"), | |
| ], | |
| "accent_class": "ct", | |
| }, | |
| { | |
| "key": "mr", | |
| "index": "02", | |
| "title": "NV-Generate · MR", | |
| "subtitle": "Multi-contrast, multi-anatomy synthetic MRI.", | |
| "icon": SVG_MR, | |
| "icon_caption": "Multi-contrast · multi-region", | |
| "uses": ["Modality augmentation", "Cross-region training", "Fine-tune base"], | |
| "license": "NVIDIA Non-Commercial", | |
| "license_tone": "warn", | |
| "spec": [ | |
| ("MODALITY", "Magnetic Resonance"), | |
| ("ARCHITECTURE", "MAISI-v2 · Rectified Flow"), | |
| ("MAX VOLUME", "512 × 512 × 128 vox"), | |
| ("CONTRASTS", "T1 · T2 · FLAIR · multi-region"), | |
| ("LICENSE", "NVIDIA Non-Commercial"), | |
| ], | |
| "accent_class": "mr", | |
| }, | |
| { | |
| "key": "mr_brain", | |
| "index": "03", | |
| "title": "NV-Generate · MR Brain", | |
| "subtitle": "High-resolution multi-contrast brain MRI.", | |
| "icon": SVG_MRB, | |
| "icon_caption": "Brain · multi-sequence", | |
| "uses": ["Brain segmentation data", "Lesion augmentation", "Sequence translation"], | |
| "license": "NVIDIA Open Model", | |
| "license_tone": "ok", | |
| "spec": [ | |
| ("MODALITY", "MR · Brain"), | |
| ("ARCHITECTURE", "MAISI-v2 · Rectified Flow"), | |
| ("MAX VOLUME", "512 × 512 × 256 vox"), | |
| ("SEQUENCES", "T1 · T2 · FLAIR · SWI"), | |
| ("LICENSE", "NVIDIA Open Model"), | |
| ], | |
| "accent_class": "mrb", | |
| }, | |
| ] | |
| def _spec_rows(spec: list[tuple[str, str]]) -> str: | |
| rows = [] | |
| for k, v in spec: | |
| rows.append( | |
| f'<div class="ds-row"><span class="ds-key">{k}</span>' | |
| f'<span class="ds-leader"></span>' | |
| f'<span class="ds-val">{v}</span></div>' | |
| ) | |
| return "".join(rows) | |
| def render_hero() -> tuple[gr.Group, dict[str, gr.Button]]: | |
| """Build the hero. Returns the wrapping Group and a dict of {key: button}.""" | |
| buttons: dict[str, gr.Button] = {} | |
| with gr.Group(elem_classes=["hero"]) as group: | |
| # Masthead: brand on the left, real links on the right. No decorative pills. | |
| gr.HTML( | |
| """ | |
| <div class="masthead"> | |
| <div class="masthead-brand"> | |
| <span class="nv-mark">NV</span> | |
| <span class="masthead-name">NV-Generate</span> | |
| </div> | |
| <nav class="masthead-nav"> | |
| <a href="https://github.com/NVIDIA-Medtech/NV-Generate-CTMR" target="_blank" rel="noopener">GitHub</a> | |
| <span class="masthead-sep"></span> | |
| <a href="https://huggingface.co/nvidia/NV-Generate-CT" target="_blank" rel="noopener">Hugging Face</a> | |
| <span class="masthead-sep"></span> | |
| <a href="https://arxiv.org/abs/2508.05772" target="_blank" rel="noopener">MAISI-v2 paper</a> | |
| </nav> | |
| </div> | |
| """ | |
| ) | |
| # Hero headline — eyebrow + bold title, no marketing paragraph below. | |
| gr.HTML( | |
| """ | |
| <div class="hero-mono"> | |
| <div class="hero-eyebrow"> | |
| <span class="line-tick"></span> | |
| <span>Latent diffusion · MAISI-v2 · open weights</span> | |
| </div> | |
| <h1 class="hero-title"> | |
| Synthetic 3D medical imaging. | |
| </h1> | |
| </div> | |
| """ | |
| ) | |
| # Datasheet cards — three equal-height subsystems | |
| with gr.Row(elem_classes=["hero-row"], equal_height=True): | |
| for card in CARDS: | |
| with gr.Column(scale=1, min_width=300, elem_classes=["hero-card-col"]): | |
| uses_html = "".join( | |
| f'<span class="ds-use">{u}</span>' for u in card.get("uses", []) | |
| ) | |
| license_tone_cls = "ds-license-warn" if card.get("license_tone") == "warn" else "ds-license-ok" | |
| gr.HTML( | |
| f""" | |
| <div class="ds-card ds-{card['accent_class']}"> | |
| <div class="ds-corner ds-tl"></div> | |
| <div class="ds-corner ds-tr"></div> | |
| <div class="ds-corner ds-bl"></div> | |
| <div class="ds-corner ds-br"></div> | |
| <div class="ds-banner"> | |
| <div class="ds-banner-grid"></div> | |
| <div class="ds-banner-icon">{card['icon']}</div> | |
| <div class="ds-banner-caption">{card['icon_caption']}</div> | |
| </div> | |
| <div class="ds-frame"> | |
| <div class="ds-head"> | |
| <div class="ds-index">{card['index']}</div> | |
| <div class="ds-status"> | |
| <span class="dot dot-pulse"></span>Available | |
| </div> | |
| </div> | |
| <div class="ds-name"> | |
| <div class="ds-name-title">{card['title']}</div> | |
| <div class="ds-name-sub">{card['subtitle']}</div> | |
| </div> | |
| <div class="ds-uses-label">Use cases</div> | |
| <div class="ds-uses">{uses_html}</div> | |
| <div class="ds-divider"></div> | |
| <div class="ds-spec"> | |
| {_spec_rows(card['spec'])} | |
| </div> | |
| <div class="ds-license {license_tone_cls}"> | |
| <span class="ds-license-k">License</span> | |
| <span class="ds-license-v">{card['license']}</span> | |
| </div> | |
| </div> | |
| </div> | |
| """ | |
| ) | |
| btn = gr.Button( | |
| f"Launch {card['title'].replace(' · ', ' ')} →", | |
| elem_classes=["ds-cta", f"ds-cta-{card['accent_class']}"], | |
| ) | |
| buttons[card["key"]] = btn | |
| return group, buttons | |