Skip to content

biodev/EAGLE

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

39 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

EAGLE

Campanella G, Kumar N, Nanda S, Singi S, Fluder E, Kwan R, Muehlstedt S, Pfarr N, Schüffler PJ, Häggström I, Neittaanmäki N, Akyürek LM, Basnet A, Jamaspishvili T, Nasr MR, Croken MM, Hirsch FR, Elkrief A, Yu H, Ardon O, Goldgof GM, Hameed M, Houldsworth J, Arcila M, Fuchs TJ, Vanderbilt C. Real-world deployment of a fine-tuned pathology foundation model for lung cancer biomarker detection. Nat Med. 2025 Sep;31(9):3002-3010. doi: 10.1038/s41591-025-03780-x. Epub 2025 Jul 9. PMID: 40634781; PMCID: PMC12443599.

Setting Up the Environment

  1. Clone the Repository:

    git clone https://github.com/chadvanderbilt/EAGLE.git
  2. Create and Activate a Conda Environment:

    conda create -n irt_env python=3.9 --file requirements.txt
    conda activate irt_env

Training (Fine-Tuning)

We fine-tuned the tile-level encoder of Prov-GigaPath and used Gated MIL attention (Ilse et al. 2019) as slide-level aggregator to predict EGFR mutational status in lung adenocarcinoma. The fine-tuning algorithm is described in detail in Campanella et al. 2024. Training was parallelized over 24 H100 GPUs. We used the LSF scheduler for job submission. The training submission script that we used can be found at training/train.lsf. Note: the script was redacted to remove cluster-specific details. LSF parameters may need to be modified. The training can be performed by

cd training
bsub < train.lsf

with lsf or for slurm hpc:

cd training
sbatch train.slurm

To run correctly, the pipeline expects the path of two files to be included in the training/datasets.py script:

  • slide_data.csv: a file containing the name, path, target, and data split for each slide in the dataset.
  • tile_data.csv: a file containing the slide name, x, and y coordinates as well as the level (within the slide file) and a rescale factor for each tile in the dataset. The rescale factor may be necessary if the right magnification is not available in the slide.

To finetune GigaPath, access to their weights is necessary via HuggingFace. Package requirements in conda irt_env.

Model Calibration

This section explains how to select the model thresholds for deployment in a new institution. We provide an example csv file: calibration/test_data.csv. The script calibration/pretrial_tuning.py illustrates the analysis we performed. To simulate the deployment of EAGLE one can do:

import numpy as np
import pandas as pd
import utils
df = pd.read_csv('example_data.csv')
utils.simulation(df)

To evaluate the performance of the assisted workflow after selecting the thresholds one can do:

import numpy as np
import pandas as pd
import utils
df = pd.read_csv('example_data.csv')
threshold_npv = 0.023
threshold_ppv = 0.997
utils.get_performance_assisted_bootstrapped(df, th0=[threshold_npv], th1=[threshold_ppv], n=1000, target_col='target', rapid_col='rapid', eagle_col='score')

More details about parameters of these functions can be found by:

import utils
help(utils.simulation)
help(utils.plot_simulation)
help(utils.get_performance_assisted_bootstrapped)

Running the IRT Pipeline

This section explains how to set up and run the IRT Pipeline for monitoring and processing scanned slides in real-time. The repository is hosted at EAGLE GitHub Repository and the relevant shell scripts are located in the IRT_Pipeline subfolder.

1. Monitoring Script (run.sh)

The run.sh script monitors newly scanned slides every hour and generates manifests for downstream processing.

Cron Job Setup:

To schedule this script to run every hour, offset by 30 minutes from the run_full_gigapath_pipeline.sh, add the following to your crontab:

crontab -e

Add this line to schedule run.sh:

30 * * * * /path/to/EAGLE/IRT_Pipeline/run.sh

2. Full Pipeline Script (run_full_gigapath_pipeline.sh)

The run_full_gigapath_pipeline.sh script processes all slides identified by the monitoring script.

Cron Job Setup:

To run the full pipeline every hour on the hour, add the following to your crontab:

0 * * * * /path/to/EAGLE/IRT_Pipeline/run_full_gigapath_pipeline.sh

Directory Structure

The scripts assume the following directory structure for outputs and logs:

/your/production/
├── logs/
│   └── irt_monitor/         # Logs generated by the monitoring script
├── slide_data/              # Manifests and slide data outputs
└── run_EGFR/                # Directory where the pipeline outputs. BASE_DIR is run_EGFR
    ├── molecular_watcher/   # Directory for monitoring molecular data
    ├── slides_to_run/       # Directory containing slides to be processed
    ├── EGFR_results/        # Directory for EGFR test results
    ├── tmp_files/           # Temporary files directory
    └── checkpoints/         # Model checkpoints directory

Ensure these directories exist or are correctly specified in the shell scripts. Adjust paths as needed for your environment. Our laboratory has API endpoints available for Real Time data. If such data is available via database then adjust as needed.

Logging

Each execution of the run.sh script will generate a log file in /your/production/logs/irt_monitor/, with filenames formatted as YYYY-MM-DD_HH-MM-SS.log.

Example Run

To manually execute the monitoring script and generate manifests:

bash /path/to/EAGLE/IRT_Pipeline/run.sh

To manually execute the full pipeline script:

bash /path/to/EAGLE/IRT_Pipeline/run_full_gigapath_pipeline.sh

You can find the new paths in https://github.com/chadvanderbilt/EAGLE/tree/main/quick_inference


Quick Inference

This module provides a minimal interface for running Gigapath-based inference using fine-tuned EAGLE model weights.
It is designed for rapid evaluation or testing of pre-trained pathology foundation models without running the full IRT pipeline.

1. Overview

The quick inference workflow performs the following:

  1. Reads a directory of whole-slide images (.svs, .tif, .ndpi, etc.)
  2. Extracts tiles and generates embeddings using the fine-tuned tile-level encoder
  3. Aggregates features using the slide-level MIL attention model
  4. Produces slide-level predictions saved to a .csv file

2. Files

quick_inference/
├── run_eagle_full.py        # Standalone inference pipeline (dir of .svs → CSV)
├── run_eagle_full.sh        # Bash wrapper
├── checkpoints/             # Place weights here (see below)
└── outputs/                 # Thumbnails + results CSV

3. Environment

conda activate irt_env
pip install -r ../requirements.txt
export CUDA_VISIBLE_DEVICES=0   # optional

4. Download EAGLE Weights

Weights are hosted at: https://huggingface.co/MCCPBR/EAGLE/tree/main

mkdir -p quick_inference/checkpoints
cd quick_inference/checkpoints
wget https://huggingface.co/MCCPBR/EAGLE/resolve/main/gigapath_ft_checkpoint_tile_020.pth
wget https://huggingface.co/MCCPBR/EAGLE/resolve/main/gigapath_ft_checkpoint_slide_020.pth

Or via CLI:

pip install -U "huggingface_hub>=0.21"
huggingface-cli download MCCPBR/EAGLE gigapath_ft_checkpoint_tile_020.pth --local-dir checkpoints
huggingface-cli download MCCPBR/EAGLE gigapath_ft_checkpoint_slide_020.pth --local-dir checkpoints

5. Configure Paths

Edit quick_inference/run_eagle_full.sh:

PYTHON_BIN="~/anaconda3/envs/EAGLE/bin/python"
SCRIPT_PATH="~/EAGLE/quick_inference/run_eagle_full.py"
SLIDES_DIR="/path/to/slides"
TILE_CKPT="~/EAGLE/quick_inference/checkpoints/gigapath_ft_checkpoint_tile_020.pth"
SLIDE_CKPT="~/EAGLE/quick_inference/checkpoints/gigapath_ft_checkpoint_slide_020.pth"
OUTDIR="~/EAGLE/quick_inference/outputs"
OUTNAME="results.csv"

6. Run

cd quick_inference
bash run_eagle_full.sh

Pass-through arguments to the Python script are supported, e.g.:

bash run_eagle_full.sh --batch_size 32 --workers 8 --recursive

7. Adaptive Runtime (GPU/CPU) — How It Works

run_eagle_full.py automatically selects the best device and remains robust under tight memory:

  • GPU selection by free VRAM
    At runtime, the script queries each visible CUDA device and picks the GPU with the most free memory.
    The minimum required free memory is configurable with --gpu_min_free_gb (default 2.0).

    • If the best GPU has ≥ gpu_min_free_gb, it’s used.
    • If no GPU meets the threshold, it still uses the best available GPU unless a strict mode is enforced (not default).
    • If no CUDA is available at all, it falls back to CPU automatically.
  • CUDA OOM auto-retry on CPU
    If a CUDA out-of-memory error happens mid-slide, the script retries that slide on CPU with conservative settings (batch size 1, workers 0).
    This is not recommended for performance, but ensures the pipeline completes and produces a score.

  • Conservative CUDA + cuCIM settings
    The script configures PYTORCH_CUDA_ALLOC_CONF=max_split_size_mb:64 and disables cuCIM caches to reduce allocator pressure.

  • Pinned memory / workers
    DataLoader uses pin_memory=True, persistent_workers=True when on GPU, and you can set --workers (default 0; if GPU is used and workers=0, it promotes to 2).

  • Flags you may care about

    • --gpu_min_free_gb FLOAT (default 2.0) – lower if your GPU is small, raise if you want to be stricter.
    • --batch_size INT – tile embedding batch size.
    • --workers INT – dataloader workers.

TL;DR: it prefers the roomiest GPU; if CUDA isn’t present or memory is too tight, it gracefully runs on CPU so the job still finishes.

8. Other Behavior & Outputs

  • Slide discovery: by default it scans slides_dir for *.svs; add --recursive to search subfolders.
  • Thumbnails & tile-grid overlays: a clean thumbnail and a red-box tile grid are saved under outputs/thumbnails/.
  • CSV schema (append-only, resumes automatically if already present):
    • slide, slide_path, target, score, inference_time, n_tiles, level, thumbnail_path, thumbnail_clean_path
  • Skip logic: if a slide already has a valid row (score present and n_tiles>0), it is skipped on subsequent runs.
  • Hugging Face tokens: if the backbone is gated, pass --hf_token or export HF_TOKEN/HUGGING_FACE_HUB_TOKEN.

9. Example Commands

Local run:

bash quick_inference/run_eagle_full.sh

Force small GPU threshold and more workers:

bash quick_inference/run_eagle_full.sh --gpu_min_free_gb 1.0 --batch_size 32 --workers 8

Recursive search:

bash quick_inference/run_eagle_full.sh --recursive

10. HPC (Slurm)

Create run_inference.slurm:

#!/usr/bin/env bash
#SBATCH --job-name=eagle_infer
#SBATCH --gres=gpu:1
#SBATCH --cpus-per-task=8
#SBATCH --mem=64G
#SBATCH --time=4:00:00
#SBATCH --output=logs/%x_%j.out
#SBATCH --error=logs/%x_%j.err

module load anaconda
source activate irt_env

cd $SLURM_SUBMIT_DIR/quick_inference
bash run_eagle_full.sh --batch_size 32 --workers 8

Submit:

sbatch run_inference.slurm

11. Notes

  • Prefer absolute paths on HPC.
  • Log stdout/stderr:
    bash run_eagle_full.sh > logs/inference_$(date +%Y%m%d_%H%M%S).log 2>&1
  • Recommended GPU: ≥24 GB VRAM (A100/H100).
  • Record the Hugging Face commit hash of weights for reproducibility.

References
Campanella et al., Fine-Tuning Pathology Foundation Models for EGFR Prediction in Lung Adenocarcinoma, 2024.
Prov-GigaPath pretrained model: https://huggingface.co/prov-gigapath/prov-gigapath

About

Repository in Support of EAGLE Submission

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • Python 88.4%
  • Shell 7.6%
  • R 4.0%