Skip to content

Repository files navigation

EXPRESSO: Drug Response Prediction Framework

Data availability: The data/ directory is not included in this repository. It is archived separately on Zenodo (DOI: 10.5281/zenodo.21878615) and must be downloaded and unpacked into your local clone — see Downloading the Data below.

Overview

EXPRESSO (EXpression-Profile-RESponSe-Optimizer) is a drug-specific supervised LASSO logistic regression framework for transcriptome-based treatment response prediction. It evaluates predictive power of drug targets and biomarkers across patient cohorts using a Leave-One-Cohort-Out Cross-Validation (LOCOCV) strategy.

Two model variants are implemented:

  • EXPRESSO-T: LASSO model with the known drug target gene(s) as penalty-free (regularization-exempt) features, with the rest of the transcriptome included as penalized predictors.
  • EXPRESSO-B: Extends EXPRESSO-T by additionally including context-specific biomarkers — identified via a nested LOCOCV differential expression procedure — as penalty-free features alongside the target gene(s).

Two baseline models are included for comparison:

  • Vanilla LASSO (noTarget mode): Supervised LASSO with no biological prior; the full transcriptome is penalized equally.
  • Unsupervised target-only: Ranks patients by the expression of the target gene alone, with no model training.

Repository Structure

project/
│
├── expresso_all.R                         # Main LOCOCV script (EXPRESSO-T / -B / vanilla)
├── expresso_biomarker_search.R            # Nested LOCOCV biomarker discovery (EXPRESSO-B)
├── gene_signature_benchmarking.R          # Gene signature benchmarking (LOCOCV)
├── expressoT_MLmodels_generate.py         # Train/evaluate alternative ML models (EXPRESSO-T context)
├── expressoB_MLmodels_generate.py         # Train/evaluate alternative ML models (EXPRESSO-B context)
├── Methods_benchmarking.ipynb             # Jupyter notebook: Other methods benchmarking walkthrough
├── source_EXPRESSO_func.R                 # All shared R helper functions
├── renv.lock                              # Pinned R package versions (see Software Requirements)
├── renv/                                  # renv scaffolding (activate.R, settings.json)
├── SESSION_INFO.txt                       # sessionInfo() from the original analysis environment
├── environment.yml                        # Conda environment for the Python benchmarking scripts
├── spec-file.txt                          # Exact conda package spec (alternate reproducible install)
│
├── prospective/                           # Prospective / independent validation pipeline
│   ├── source_EXPRESSO_func.R             # All shared R helper functions
│   ├── expresso_prospective_predict.R     # Get prediction for new cohort(s)
│   ├── expresso_single_cohort_predict.sh  # Shell script to run full prospective pipeline
│   ├── pooled_models/                     # Pooled models trained on all original cohorts, per drug
│   ├── prospec_data/                      # Independent/prospective test cohorts -NOT included in this repo — download from Zenodo (DOI: 10.5281/zenodo.21878615 (https://doi.org/10.5281/zenodo.21878615)) (same layout as data/)
│   └── expresso_test_prospec/             # Prediction outputs (AUC summaries) written here
│
├── data/                                   # NOT included in this repo — download from Zenodo
│   │                                       # (see "Downloading the Data" below); layout once unpacked:
│   ├── <cohort>/                          # One directory per drug cohort group
│   │   ├── metadata.tsv                   # Cohort metadata (cohort, cancer, type, drug, targets)
│   │   │                                  # TRAINING COHORTS ONLY — test cohorts must be excluded
│   │   ├── response.tsv                   # Sample-level treatment response labels
│   │   └── mrna/
│   │       └── <cohort_id>.rds            # Expression matrix (genes × samples, numeric matrix)
│   ├── biomarkers/
│   │   └── <cohort>_biomarkers.tsv        # Per-fold target/biomarker gene definitions
│   └── MultiAssayExperiment/
│       └── MAE_<drug>.rds                 # Publicly available cohorts as MAE objects, per drug
│
├── comparisons/
│   ├── final_signatures.tsv               # Index of all 16 published gene signatures
│   ├── <signature_name>.tsv               # One file per gene signature (gene lists)
│   └── ...
│
└── results/                               # All output TSV files written here

prospective/pooled_models/ is included directly in this repository. The top-level data/ directory (original training cohorts, biomarker gene lists, and MultiAssayExperiment objects) and prospective/prospec_data/ are hosted separately on Zenodo due to its size — see Downloading the Data below.


Downloading the Data

The data/ directory — cohort-level expression matrices, response labels, biomarker gene lists, and MultiAssayExperiment objects — is archived separately on Zenodo rather than committed to this repository.

prospective/pooled_models/ and prospective/prospec_data/ are already included in this GitHub repository and do not require this step — only the top-level data/ directory needs to be downloaded.

Steps

  1. Clone this repository, if you haven't already, and cd into it:

    git clone https://github.com/ruppinlab/EXPRESSO.git
    cd EXPRESSO
  2. Download the archive from Zenodo:

    curl -L -o expresso_aug2026.tar.gz \
      "https://zenodo.org/records/21878615/files/expresso_aug2026.tar.gz?download=1"

    (or use wget -O expresso_aug2026.tar.gz "<same URL>", or download it directly from the Zenodo record page in a browser)

  3. Extract the archive:

    tar -xzf expresso_aug2026.tar.gz
  4. Move the extracted data/ directory into the repository root, so it sits alongside comparisons/ and prospective/. Place the prospective/prospec_data/ directory for validation cohorts. Check where extraction placed it first — some archive tools unpack into their own top-level folder (e.g. expresso_aug2026/data/) rather than directly into the current directory:

    ls                                   # confirm where data/ landed after extraction
    mv expresso_aug2026/data ./data      # adjust the source path if it differs
  5. Confirm the directory landed in the right place:

    ls data
    # beva  biomarkers  brafi  cyclop  MultiAssayExperiment  pacli  pd1mel  pd1oth  tras
  6. (Optional) remove the downloaded archive once extraction is confirmed:

    rm expresso_aug2026.tar.gz

Once data/ is in place, the repository matches the structure described throughout this README, and the pipeline can be run as documented below.


Input Data Format

metadata.tsv

Column Description
cohort Unique cohort identifier (e.g. GSE78220)
cancer Cancer type
type Sample type
drug Drug/intervention name
targets Drug target gene(s)

response.tsv

Column Description
cohort Cohort identifier (must match metadata.tsv)
sample Sample ID (must match column names in expression matrix)
response Responder or Non-responder

mrna/<cohort_id>.rds

A numeric R matrix with genes as row names and sample IDs as column names. Gene expression values should be in raw or log-scale; normalization is applied internally (see Normalization section).

data/biomarkers/<cohort>_biomarkers.tsv

Column Description
test_id Cohort held out as test set for this fold
target Comma-separated target gene(s) for target mode
biomarkers Comma-separated biomarker genes for biomarker mode

Normalization

Raw gene expression values are rank-normalized within each sample (converting expression values to fractional ranks in [0, 1]) using the rank_normalization() function in source_EXPRESSO_func.R. This within-sample normalization is applied uniformly across all cohorts prior to model training.

The --normalization argument (default: "ranked") controls this behavior:

Value Description
ranked Within-sample rank normalization to [0,1] — default, recommended
NPN Nonparanormal transformation (rank + probit)
raw No normalization applied

Software Requirements

R (≥ 4.0)

This repository includes an renv.lock file (plus renv/activate.R and renv/settings.json) that pins the exact R package versions used for the analysis. Recommended setup:

install.packages("renv")
renv::restore()   # reads renv.lock and installs the matching package versions

SESSION_INFO.txt records the full sessionInfo() output from the original analysis environment as an additional reference if you need to check a specific package version.

Alternatively, install the required packages manually:

install.packages(c(
  "tidyverse", "data.table", "glmnet", "caret",
  "rsample", "pROC", "limma", "parallel", "metap"
))

# For differential expression:
if (!requireNamespace("BiocManager", quietly = TRUE))
  install.packages("BiocManager")
BiocManager::install("limma")

Python (3.11)

pip install numpy pandas scipy matplotlib

This repository also includes environment.yml and spec-file.txt for reproducing the exact conda environment used for the benchmarking scripts:

conda env create -f environment.yml
# or, for an exact package-for-package match:
conda create --name expresso --file spec-file.txt

Random Seeds

All stochastic procedures use fixed random seeds for full reproducibility:

  • set.seed(31052024) is called immediately before each cv.glmnet() model build in source_EXPRESSO_func.R
  • The bootstrap CI functions in the Python comparison scripts use np.random.default_rng(42)

Scripts and Usage

1. expresso_all.R — Main LOCOCV (EXPRESSO-T / -B / noTarget)

Runs LOCOCV for a single drug and produces AUCs, odds ratios, and selected features.

Rscript expresso_all.R <intervention> <cohort> <biomarker_file> <mode> [normalization] [response_weights]
Argument Description
intervention Drug name (e.g. ICB, trastuzumab)
cohort Cohort directory under data/ (e.g. pd1mel)
biomarker_file TSV file under data/biomarkers/ with per-fold target/biomarker genes
mode target (EXPRESSO-T), biomarker (EXPRESSO-B), or noTarget
normalization (optional) ranked (default), NPN, or raw
response_weights (optional) TRUE (default) or FALSE

Drug-cohort reference table:

Drug intervention cohort biomarker_file
ICB – melanoma ICB pd1mel pd1mel_biomarkers.tsv
ICB – non-melanoma ICB pd1oth pd1oth_biomarkers.tsv
Trastuzumab trastuzumab tras tras_biomarkers.tsv
Bevacizumab bevacizumab beva beva_biomarkers.tsv
BRAFi BRAFi brafi brafi_biomarkers.tsv
Paclitaxel paclitaxel pacli pacli_biomarkers.tsv
Chemo-FAC-FEC cyclophos cyclop cyclop_biomarkers.tsv

Examples:

# EXPRESSO-T for Chemo-FAC-FEC
Rscript expresso_all.R cyclophos cyclop cyclop_biomarkers.tsv target

# EXPRESSO-B for ICB-melanoma
Rscript expresso_all.R ICB pd1mel pd1mel_biomarkers.tsv biomarker

# Vanilla LASSO (no target prior) for paclitaxel
Rscript expresso_all.R paclitaxel pacli pacli_biomarkers.tsv noTarget

Outputs written to results/:

File Contents
<intervention>_<cohort>_<mode>_expresso_AUCs.tsv Per-cohort AUC and odds ratio (mid.OR), plus Mean/Median summary rows
<intervention>_<cohort>_<mode>_expresso_features.tsv Genes selected per fold with LASSO coefficients
<intervention>_<cohort>_<mode>_expresso_features_frequency.tsv Aggregated gene selection frequency across all folds

Note on filename convention for downstream comparison scripts: The Python comparison scripts (expressoT_MLmodels_generate.py, expressoB_MLmodels_generate.py) expect AUC files named <intervention>_LOCOCV_lasso_AUCs.tsv. Rename or symlink the output from expresso_all.R accordingly before running comparison scripts.


2. expresso_biomarker_search.R — Biomarker Discovery (Nested LOCOCV)

Runs the nested LOCOCV biomarker discovery procedure used to produce the per-fold biomarker gene lists for EXPRESSO-B. For each outer fold, identifies differentially expressed genes from the training cohorts using limma, combines fold-level p-values using Brown's method (to account for inter-fold dependence from overlapping training sets), and selects genes that improve LOCOCV AUC by ≥ 0.02 (ΔAUC criterion).

Rscript expresso_biomarker_search.R <intervention> <cohort> <target> [options]
Argument Description
intervention Drug name
cohort Cohort identifier
target Target gene(s), comma-separated (e.g. CD274 or TOP2A,TYMS)

Key options:

Option Default Description
--de_fdr 0.05 FDR cutoff for DE gene selection
--de_logfc 0.4 Minimum mean absolute log-fold-change
--delta_auc 0.02 Minimum ΔAUC to accept a biomarker gene
--delta_pval 0.05 Wilcoxon p-value threshold for ΔAUC test
--max_biom 3 Maximum biomarker genes to add per fold
--ncores auto Parallel cores for deltaAUC computation
--result_dir <cohort>_cv_fold_results Output directory

Examples:

Rscript expresso_biomarker_search.R ICB pd1mel CD274
Rscript expresso_biomarker_search.R trastuzumab tras ERBB2 --ncores 8 --max_biom 3

Outputs written to --result_dir:

File Contents
<intervention>_<cohort>_cv_result_<test_id>.rds Per-fold RDS with DE summary, deltaAUC results, selected biomarker genes
<intervention>_<cohort>_summary_auc_results.tsv Summary AUC table across all folds

The per-fold RDS files are used to populate the biomarkers column in <cohort>_biomarkers.tsv for input to expresso_all.R.


3. gene_signature_benchmarking.R — Published Signature Benchmarking

Evaluates a set of published gene signatures against all cohorts in a prospective (non-cross-validated) manner. Each signature is scored by the mean rank-normalized expression of its member genes; AUC is computed per cohort.

Rscript gene_signature_benchmarking.R <intervention> <cohort> <signatures_file> [options]
Argument Description
intervention Drug name (used in output filename)
cohort Cohort identifier
signatures_file TSV file with a signatures column listing signature names

Key options:

Option Default Description
--sig_dir comparisons Directory containing per-signature TSV gene list files
--result_dir comparisons Directory for output TSV
--drug_label same as intervention Human-readable label in output table

Example:

Rscript gene_signature_benchmarking.R trastuzumab tras comparisons/final_signatures.tsv \
  --sig_dir comparisons --result_dir results --drug_label "Trastuzumab"

Output: <intervention>_<cohort>_aucs_comparison_gene_signatures_long_loco_pros.tsv

Contains columns: cohort, AUC, drug, predictor (signature name).

The comparisons/ directory contains gene lists for all 16 published signatures used for benchmarking (e.g., TIDE, IMPRES, CYT, MammaPrint, OncotypeDX), each as a separate TSV file, along with references to the original publications. Signatures were implemented according to their original scoring procedures using the same rank-normalized expression data as EXPRESSO.


4. expressoT_MLmodels_generate.py / expressoB_MLmodels_generate.py — Alternative ML Models

Generate LOCOCV AUC results for alternative machine learning models (Random Forest, XGBoost, SVM, KNN, MLP) in the EXPRESSO-T and EXPRESSO-B contexts respectively, for direct comparison with EXPRESSO. Both scripts also run paired Wilcoxon signed-rank tests against the LASSO reference, compute bootstrap 95% confidence intervals, and produce a publication-ready boxplot.

Output files follow the naming convention:

results/<intervention>_LOCOCV_<model>_AUCs.tsv
python expressoT_MLmodels_generate.py \
  --results_dir results \
  --intervention ICBmel \
  --reference lasso \
  --output_dir figures

python expressoB_MLmodels_generate.py \
  --results_dir results \
  --intervention ICBmel \
  --reference lasso \
  --output_dir figures
Option Default Description
--results_dir (required) Directory with <intervention>_LOCOCV_<model>_AUCs.tsv files
--intervention (required) Drug name matching the file prefix
--reference lasso Reference model for Wilcoxon test
--min_cohort_size 0 Minimum cohort size filter
--output_dir figures Directory for output PDF/PNG and stats TSV
--n_boot 2000 Bootstrap iterations for CI computation

Outputs:

File Contents
<intervention>_model_stats.tsv Mean AUC, 95% CI, Wilcoxon statistic, p-value, significance per model
<intervention>_boxplot_AUC.pdf/.png Boxplot with per-cohort AUCs, jittered points, and significance stars

5. Methods_benchmarking.ipynb — Walkthrough Notebook

A Jupyter notebook demonstrating a full end-to-end run of EXPRESSO-T and EXPRESSO-B for a single drug and cohort, including data loading, model training, AUC evaluation, and signature benchmarking. Intended as a reproducibility reference and example for new users.


Prospective Validation

The prospective/ directory contains scripts for applying a trained EXPRESSO model to new, completely unseen cohorts. Pre-trained pooled models (pooled_models/) and the independent/prospective cohort data (prospec_data/) are already included under prospective/, so reproducing the manuscript's prospective results only requires the prediction step below — no separate model training or download is needed.

Data organisation for prospective validation

data/
└── <cohort>/
    ├── metadata.tsv    ← TRAINING cohorts only (test cohorts must be excluded)
    ├── response.tsv
    └── mrna/

prospective/
├── prospec_data/
│   └── <cohort>/
│       ├── metadata.tsv    ← TEST cohorts only
│       ├── response.tsv
│       └── mrna/
│           └── <cohort_id>.rds
│
├── pooled_models/          ← pooled model trained on all original cohorts, per drug
│   ├── <intervention>_<cohort>_target_expresso_pooled_model.rds
│   ├── <intervention>_<cohort>_target_gene_list.tsv
│   └── <intervention>_<cohort>_target_scale_params.rds   ← training-data scaling params, applied to new cohorts before prediction
│
└── expresso_test_prospec/  ← prediction outputs written here

Important: data/<cohort>/metadata.tsv must contain training cohorts only. Test cohorts must be completely absent from this file. Mixing them in will produce a model that has seen the test data during training, invalidating the prospective evaluation.


6. prospective/expresso_prospective_predict.R — Predict on New Cohort(s)

Loads a saved pooled model and evaluates it on one or more new cohorts. Uses summarize_ORs() from source_EXPRESSO_func.R exactly as the training pipeline does, so AUC and OR values are directly comparable to LOCOCV results.

Rscript prospective/expresso_prospective_predict.R \
  <model_rds> <gene_list_tsv> <data_dir> [cohort_names] [normalization]
Argument Description
model_rds Path to pooled model RDS, e.g. prospective/pooled_models/<...>_expresso_pooled_model.rds
gene_list_tsv Path to the matching gene list TSV in the same directory
data_dir Directory with metadata.tsv, response.tsv, mrna/ for test cohorts
cohort_names (optional) comma-separated cohort IDs to evaluate — default: all in directory
normalization (optional) ranked (default) — must match what was used during training

The matching <...>_scale_params.rds file in pooled_models/ is loaded automatically alongside the model to standardize new-cohort expression consistently with training.

Examples:

# Evaluate all cohorts in the prospective directory
Rscript prospective/expresso_prospective_predict.R \
  prospective/pooled_models/trastuzumab_tras_target_expresso_pooled_model.rds \
  prospective/pooled_models/trastuzumab_tras_target_gene_list.tsv \
  prospective/prospec_data/tras

# Evaluate specific cohorts only
Rscript prospective/expresso_prospective_predict.R \
  prospective/pooled_models/ICB_pd1oth_target_expresso_pooled_model.rds \
  prospective/pooled_models/ICB_pd1oth_target_gene_list.tsv \
  prospective/prospec_data/pd1oth \
  GSE281729_p1,GSE281729_p2,GSE274975

Output written to prospective/expresso_test_prospec/:

File Contents
<intervention>_<cohort>_<mode>_<dir>_AUC_summary.tsv Per-cohort AUC and OR (mid.OR), plus Mean/Median summary rows

6b. prospective/expresso_single_cohort_predict.sh — Run Full Prospective Pipeline

Shell wrapper that runs expresso_prospective_predict.R for all drug/cohort combinations below in one call:

bash prospective/expresso_single_cohort_predict.sh

Drug-cohort reference for prospective validation:

Drug intervention cohort Test cohorts
ICB – melanoma ICB pd1mel davar24
ICB – non-melanoma ICB pd1oth GSE281729_p1, GSE281729_p2, GSE274975
ICB – lung (NSCLC-specific sub-model of pd1oth) ICB icblung GSE274975
Trastuzumab trastuzumab tras GSE130788, GSE243375, phs003576
Chemo-FAC-FEC cyclophos cyclop GSE122630, GSE123845_p2, GSE14764, GSE16716, GSE21974, GSE22226, GSE231629, GSE240671_p2, GSE25066, GSE260693, GSE32603, GSE34138, GSE41656, GSE42822_p2, GSE4779

Typical Full Workflow

Step 1: Biomarker discovery (produces per-fold biomarker gene lists)
  └─ expresso_biomarker_search.R  →  <cohort>_biomarkers.tsv

Step 2: LOCOCV model evaluation
  ├─ expresso_all.R (mode=target)    →  EXPRESSO-T AUCs + features
  ├─ expresso_all.R (mode=biomarker) →  EXPRESSO-B AUCs + features
  └─ expresso_all.R (mode=noTarget)  →  Vanilla LASSO AUCs

Step 3: Alternative ML model evaluation
  ├─ expressoT_MLmodels_generate.py  →  RF, XGB, SVM, KNN, MLP AUCs (T context)
  └─ expressoB_MLmodels_generate.py  →  RF, XGB, SVM, KNN, MLP AUCs (B context)

Step 4: Signature benchmarking
  ├─ gene_signature_benchmarking.R   →  Published signature AUCs per cohort
  └─ Methods_benchmarking.ipynb      →  Interactive benchmarking walkthrough

Step 5: Statistical comparison and visualization
  ├─ expressoT_MLmodels_generate.py  →  EXPRESSO-T boxplot vs ML models
  └─ expressoB_MLmodels_generate.py  →  EXPRESSO-B boxplot vs ML models

Step 6: Prospective validation (pooled models & test cohorts already included)
  ├─ prospective/expresso_prospective_predict.R      →  Predict on new cohort(s)
  └─ prospective/expresso_single_cohort_predict.sh   →  Run all drug/cohort combinations at once

Notes

  • The helper functions in source_EXPRESSO_func.R must be in the same directory as the calling script, or the --source_file path must be updated.
  • Cohorts containing dbGaP-restricted data require data access approval; results for those cohorts will differ from the manuscript until access is granted.
  • Genes are restricted to those measured in at least 3 cohorts (controlled by gene_cohort_cutoff_) to enable consistent cross-cohort model fitting.
  • For prospective validation, data/<cohort>/metadata.tsv must contain training cohorts only. Test cohorts live in prospective/prospec_data/<cohort>/metadata.tsv.
  • The gene list embedded in the saved model (read from rownames(coef(mod))) is the authoritative source of gene ordering for prediction — it takes precedence over the gene_list.tsv file.
  • The full list of cohorts used per drug is provided in Supplementary Table S1 of the manuscript.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages