') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); GitHub - KatherLab/MediSwarm: MediSwarm is an open-source project for advancing medical deep learning using swarm intelligence and NVFlare. Developed by the Odelia consortium, it ensures data privacy through federated learning, enabling collaborative, decentralized model training across institutions for improved medical research and applications. · GitHub
Skip to content

Latest commit

History

2,344 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

MediSwarm

An open-source platform advancing medical AI via privacy-preserving swarm learning, based on NVFlare and developed with the ODELIA consortium.

PR TestsBuildDeploy TestSTAMP Deploy Test

Current release: v1.5.0 (swarm-robustness).

What is MediSwarm?

MediSwarm is a federated / swarm learning framework for medical imaging. It lets hospitals and research institutions collaboratively train deep-learning models on distributed datasets without ever sharing raw patient data. Each site trains locally inside a Docker container, and only model updates (gradients or weights) leave the institution — coordinated by an NVIDIA FLARE (NVFlare) 2.7.2 server.

MediSwarm currently ships two production pipelines — ODELIA for 3D breast MRI classification and STAMP for computational pathology — and is designed to be extended with new tasks through a simple compatibility interface (see Making Your Training Code MediSwarm-Compatible).

Quick Start for Your Role

Choose your role and follow the instructions:

System Architecture

The diagram below shows how MediSwarm connects multiple hospital sites through an NVFlare server. Each site runs training inside its own Docker container; only model updates travel over the network.

graph TB
subgraph "NVFlare Server"
S[FL Server<br/>Orchestration]
A[FedAvg / FedOpt<br/>Aggregator]
S --- A
end
subgraph "Site 1 — Hospital A"
D1[Docker Container<br/>ODELIA / STAMP]
DATA1[(Local Medical<br/>Data)]
D1 --- DATA1
end
subgraph "Site 2 — Hospital B"
D2[Docker Container<br/>ODELIA / STAMP]
DATA2[(Local Medical<br/>Data)]
D2 --- DATA2
end
subgraph "Site 3 — Hospital C"
D3[Docker Container<br/>ODELIA / STAMP]
DATA3[(Local Medical<br/>Data)]
D3 --- DATA3
end
D1 -- "model updates ↑↓ global model" --> S
D2 -- "model updates ↑↓ global model" --> S
D3 -- "model updates ↑↓ global model" --> S
style S fill:#4a90d9,stroke:#2c5f8a,color:#fff
style A fill:#5ba55b,stroke:#3a7a3a,color:#fff
style D1 fill:#e8a838,stroke:#c4872a,color:#fff
style D2 fill:#e8a838,stroke:#c4872a,color:#fff
style D3 fill:#e8a838,stroke:#c4872a,color:#fff
style DATA1 fill:#ddd,stroke:#999
style DATA2 fill:#ddd,stroke:#999
style DATA3 fill:#ddd,stroke:#999
Loading

Training Pipeline

A federated training run proceeds in rounds. The server sends the current global model to all sites, each site trains locally, and the server aggregates the returned updates.

sequenceDiagram
participant Server as NVFlare Server
participant SiteA as Site A (Docker)
participant SiteB as Site B (Docker)
participant SiteC as Site C (Docker)
Server->>Server: Initialize global model
loop Each Training Round
Server->>SiteA: Send global model
Server->>SiteB: Send global model
Server->>SiteC: Send global model
par Local Training
SiteA->>SiteA: Train on local data
SiteB->>SiteB: Train on local data
SiteC->>SiteC: Train on local data
end
SiteA->>Server: Return model updates
SiteB->>Server: Return model updates
SiteC->>Server: Return model updates
Server->>Server: Aggregate updates (FedAvg)
Server->>Server: Evaluate global model
end
Server->>SiteA: Distribute final model
Server->>SiteB: Distribute final model
Server->>SiteC: Distribute final model
Loading

Supported Pipelines

PipelineDomainInputBackbone(s)Docker ImagePythonPyTorch
ODELIABreast MRI classification3D NIfTI volumesDenseNet-121, DINOv2jefftud/odelia:1.5.03.102.2.2
STAMPComputational pathology (classification / survival)H5 feature filesVIT, MLP, TransMILjefftud/stamp:<version>3.112.7.1

ODELIA — A 3D CNN pipeline for ternary classification on breast MRI, originating from the ODELIA consortium. Uses DenseNet-121 as the default backbone with optional DINOv2 feature extraction.

STAMP — Solid Tumor Associative Modeling in Pathology, based on KatherLab STAMP 2.4.0. Operates on pre-extracted H5 feature files (not raw whole-slide images), supporting classification and survival prediction tasks with multiple attention-based backbones.

Key Features

  • Privacy by design — raw data never leaves the hospital; only model weights/gradients are transmitted
  • Dockerized reproducibility — every site runs the identical container image, eliminating environment drift
  • NVFlare 2.7.2 — built on NVIDIA's production-grade federated learning platform (local fork in docker_config/NVFlare/)
  • Multi-pipeline — supports diverse imaging modalities (3D MRI, pathology features) from a single framework
  • Provisioning & VPN — turnkey provisioning YAML files and OpenVPN guides for secure multi-site deployments
  • CI/CD — automated PR tests, integration tests, and Docker image builds via GitHub Actions
  • Live synckit_live_sync/ utilities for real-time startup kit synchronization across sites
  • Evaluation toolkit — scripts for benchmarking, log parsing, AUROC plotting, and prediction (scripts/evaluation/)

Project Structure

MediSwarm/
├── application/
│ ├── jobs/ # NVFlare job definitions
│ │ ├── ODELIA_ternary_classification/
│ │ ├── STAMP_classification/
│ │ ├── cifar10/ # Reference / smoke-test job
│ │ ├── minimal_training_pytorch_cnn/
│ │ └── _shared/ # Shared job components
│ └── provision/ # Provisioning YAML files
│ ├── project_Odelia_allsites.yml
│ ├── project_HA.yml
│ └── ...
├── docker_config/
│ ├── Dockerfile_ODELIA # ODELIA image (Python 3.10)
│ ├── Dockerfile_STAMP # STAMP image (Python 3.11)
│ ├── Dockerfile_cifar10 # Minimal test image
│ ├── NVFlare/ # Local NVFlare 2.7.2 fork
│ └── master_template.yml
├── scripts/
│ ├── build/ # Docker build & startup-kit scripts
│ ├── ci/ # CI helpers (integration tests, apt updates)
│ ├── evaluation/ # Benchmarking, log parsing, AUROC plots
│ └── client_node_setup/ # Site-level setup utilities
├── docs/ # Extended documentation
├── tests/
│ ├── integration_tests/ # End-to-end NVFlare simulation tests
│ └── unit_tests/ # Model & config unit tests
├── assets/ # Role-specific READMEs, diagrams
├── server_tools/ # Server management utilities
├── kit_live_sync/ # Startup-kit live synchronization
├── workspace/ # Runtime workspace (gitignored)
├── odelia_image.version # Current version (1.2.0)
├── pyproject.toml
├── deploy_and_test.sh # One-click deploy & test
└── README.md

License

MIT — see LICENSE.

Maintainers

Contributing

Contributions welcome! Open an issue or submit a PR.

Credits

Built on:

About

MediSwarm is an open-source project for advancing medical deep learning using swarm intelligence and NVFlare. Developed by the Odelia consortium, it ensures data privacy through federated learning, enabling collaborative, decentralized model training across institutions for improved medical research and applications.

Resources

Contributing

Security policy

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages