Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

RafaelBotan/CorePAM-Study

Open more actions menu

Repository files navigation

CorePAM: A 24-Gene PAM50-Derived Expression Score with Cross-Platform External Validation for Breast Cancer Prognosis

DOI License: MIT R >= 4.4

PhD thesis project — Rafael de Negreiros Botan

Reducing the 50-gene PAM50 panel to the smallest prognostic subset (CorePAM, 24 genes) whose out-of-fold C-index is non-inferior (delta-C <= 0.010) to the full 50-gene elastic-net Cox model. Validated across four independent cohorts spanning RNA-seq and microarray platforms.


Overview

PAM50 is the gold-standard 50-gene expression panel for breast cancer molecular classification. CorePAM asks: how few of those 50 genes are actually needed for prognostic scoring?

Using elastic-net Cox regression on the SCAN-B cohort (n = 3,069), we derived a 24-gene subset that retains non-inferior prognostic discrimination, then validated it on four independent cohorts (TCGA-BRCA, METABRIC, GSE20685, GSE1456) covering both RNA-seq and microarray platforms. A secondary analysis evaluated the CorePAM score as a predictor of pathological complete response (pCR) to neoadjuvant chemotherapy across five additional cohorts.

Key results:

  • Random-effects meta-analysis HR = 1.37 (95% CI 1.24-1.52; I2 = 38.2%; p = 1.6 x 10^-9) per 1-SD increase
  • Concordance (C-index) 0.62-0.66 across validation cohorts
  • pCR meta-analysis OR = 1.69 (95% CI 1.39-2.05; I2 = 0%)

Cohorts

Survival (Overall Survival / Disease-Specific Survival)

Cohort Role Platform Endpoint N Events Median FU
SCAN-B (GSE96058) Training RNA-seq OS 3,069 322 (10.5%) 54.9 mo
TCGA-BRCA Validation RNA-seq OS 1,072 150 (14.0%) 32.0 mo
METABRIC Validation Microarray (Illumina) DSS 1,978 646 (32.7%) 159.0 mo
GSE20685 Validation Microarray (Affymetrix) OS 327 83 (25.4%) 112.8 mo
GSE1456 Validation Microarray (Affymetrix) OS 159 40 (25.2%) 91.0 mo

pCR (Pathological Complete Response to NACT)

Cohort Role Platform N (analyzed) pCR rate
GSE25066 Primary HGU133A 182 23.1%
GSE20194 Primary HGU133Plus2 278 20.1%
GSE32646 Primary HGU133Plus2 115 23.5%
I-SPY 1 (GSE22226) Primary Agilent 44K 122 26.2%
I-SPY 2 (GSE194040) Exploratory Agilent 44K 986 32.4%

Note: pCR sample sizes reflect post-QC cohorts (complete CorePAM score + endpoint + covariates).


Repository Structure

.
├── scripts/                     R scripts (numbered 00-36)
│   ├── 00_setup.R               Environment + frozen parameters (sourced by all)
│   ├── 00_colors.R              Colour palette for all figures
│   ├── 01-04_*.R                Data download, clinical harmonisation, expression preprocessing
│   ├── 05_reduce_pam50_to_corepam_FINAL.R   CorePAM derivation (FREEZE)
│   ├── 06_*.R                   Z-score and scoring per cohort
│   ├── 07_*.R                   Survival analysis per cohort + figures
│   ├── 08_meta_survival.R       Random-effects meta-analysis (K = 4 validation cohorts)
│   ├── 11_*.R                   Incremental value (delta-C-index) + DCA
│   ├── 13-16_*.R                Quality control (correlations, PCA, schema, anti-hard-code)
│   ├── 17-18_*.R                Manuscript rendering + submission bundle
│   ├── 19-23b_*.R               pCR analysis block (download -> analysis -> meta -> figures)
│   ├── 30-36_*.R                Major revision analyses (frozen z-score, Uno's C, calibration, ER subgroup, full baseline)
│   ├── 24_integrate_GSE1456_stockholm.R   4th validation cohort integration
│   └── 25-29_*.R                Sensitivity analyses (CORE-A expanded, genefu, bootstrap, drop-gene)
│
├── results/
│   ├── corepam/                 Model artefacts (weights, Pareto, training card)
│   ├── main/                    Manuscript tables (Table 3, meta-analysis summary)
│   ├── supp/                    Supplementary tables + QC reports
│   └── pcr/                     pCR logistic results + meta-analysis
│
├── figures/
│   ├── main/en/{pdf,png}/       Main figures (vector + raster)
│   ├── supp/en/{pdf,png}/       Supplementary figures
│   └── pcr/en/{pdf,png}/        pCR figures
│
├── 01_docs/
│   ├── registry/                Frozen parameters, artefact inventory, audit reports
│   └── endpoint_mapping_templates/  Clinical endpoint mapping per cohort
│
├── manuscript/
│   └── CorePAM_manuscript.qmd   Quarto source (all numbers read from CSVs)
│
├── submission/                  Submitted manuscript (TeX, PDF, figures, supplementary files)
├── config/                      pCR cohort manifest
├── CITATION.cff                 Citation metadata
├── INSTALL.R                    One-step package installer
├── LICENSE                      MIT License
└── README.md                    This file

Data lake (01_Base_Pura_CorePAM/) is git-ignored. All raw and processed data are downloaded automatically by scripts/01_download_raw_data.R.


Frozen Parameters

All analytical parameters were pre-specified and locked before any data analysis. They are stored in 01_docs/registry/analysis_freeze.csv.

Parameter Value Description
delta_c 0.010 Non-inferiority margin for C-index
alpha 0.5 Elastic-net mixing parameter
k_folds 10 Stratified CV folds
seed_folds 42 Fold assignment seed
min_genes_fraction 0.80 Minimum gene coverage per cohort
time_unit_divisor 30.4375 Days to months conversion

Reproducibility

Requirements

Component Version
R >= 4.4.0 (developed on 4.5.2)
Quarto >= 1.4 (for manuscript rendering only)
Internet Required for initial data download
Disk space >= 15 GB
RAM >= 16 GB

Step 0 — Install packages

source("INSTALL.R")

Step 1 — Run the full pipeline

Scripts are numbered and must be executed in order. Each script sources 00_setup.R automatically and checks whether its outputs already exist (skip/force pattern — set FORCE_RERUN=TRUE to re-execute).

# Download raw data (requires internet, ~1-4 hours)
source("scripts/01_download_raw_data.R")

# Clinical harmonisation (4 cohorts)
source("scripts/02_harmonize_clinical_SCANB.R")
source("scripts/02_harmonize_clinical_TCGA_BRCA.R")
source("scripts/02_harmonize_clinical_METABRIC.R")
source("scripts/02_harmonize_clinical_GSE20685.R")

# Expression preprocessing (4 cohorts)
source("scripts/03_expression_preprocess_SCANB.R")
source("scripts/03_expression_preprocess_TCGA_BRCA.R")
source("scripts/03_expression_preprocess_METABRIC.R")
source("scripts/03_expression_preprocess_GSE20685.R")

# Gene audit + CorePAM derivation
source("scripts/04_gene_audit_freeze.R")
source("scripts/05_reduce_pam50_to_corepam_FINAL.R")

# Scoring (4 cohorts)
source("scripts/06_zscore_and_score_SCANB.R")
source("scripts/06_zscore_and_score_TCGA_BRCA.R")
source("scripts/06_zscore_and_score_METABRIC.R")
source("scripts/06_zscore_and_score_GSE20685.R")

# Survival analysis (preflight + 4 cohorts + meta)
source("scripts/07A_preflight_files_strict.R")
source("scripts/07_survival_analysis_SCANB.R")
source("scripts/07_survival_analysis_TCGA_BRCA.R")
source("scripts/07_survival_analysis_METABRIC.R")
source("scripts/07_survival_analysis_GSE20685.R")
source("scripts/08_meta_survival.R")

# Figures + tables
source("scripts/07x_extra_figures.R")
source("scripts/07y_pam50full_comparison.R")
source("scripts/07z_table_figures_survival.R")

# Incremental value + DCA
source("scripts/11_incremental_value_and_dca.R")
source("scripts/11b_dca_corepam.R")

# Quality control
source("scripts/13_qc_correlations_offdiag.R")
source("scripts/14_qc_metabric_pca_forensics.R")
source("scripts/15_qc_schema_range_checks.R")
source("scripts/16_qc_text_vs_results_assert.R")

# Manuscript rendering
source("scripts/17_render_manuscript_quarto.R")

# --- 4th validation cohort (GSE1456 / Stockholm) ---
source("scripts/24_integrate_GSE1456_stockholm.R")

# --- pCR block (secondary analysis) ---
source("scripts/19_download_pCR_raw_data.R")
source("scripts/20_prepare_pCR_GSE25066.R")
source("scripts/20_prepare_pCR_GSE20194.R")
source("scripts/20_prepare_pCR_GSE32646.R")
source("scripts/20_prepare_pCR_ISPY1.R")
source("scripts/20_prepare_pCR_ISPY2.R")
source("scripts/21_pCR_logistic_analysis.R")
source("scripts/21c_pcr_er_interaction.R")
source("scripts/21_ispy2_analysis.R")
source("scripts/22_meta_pCR.R")
source("scripts/22b_meta_pCR_with_ispy2.R")
source("scripts/23_pCR_figures.R")
source("scripts/23b_pCR_ispy2_figures.R")

# --- Sensitivity analyses ---
source("scripts/25_sensitivity_corea_expanded.R")
source("scripts/26_sensitivity_genefu_comparison.R")
source("scripts/27_bootstrap_gene_stability.R")
source("scripts/28_dropgene_sensitivity.R")
source("scripts/29_corea_sensitivity_forest.R")

# --- Major revision analyses ---
source("scripts/30_frozen_zscore_sensitivity.R")
source("scripts/31_uno_c_and_tdauc.R")
source("scripts/32_calibration_formal.R")
source("scripts/34_subgroup_er_stratified.R")
source("scripts/35_er_neg_bootstrap_stability.R")
source("scripts/36_full_clinical_baseline.R")

Step 2 — Validate

source("scripts/00_validate_all.R")

This checks syntax of all scripts and verifies that expected output files exist.


Reproducibility Safeguards

Safeguard Implementation
Frozen parameters All choices locked in analysis_freeze.csv before analysis
SHA-256 audit trail Every raw file and output artefact hashed in registry/study_registry.csv
No inter-cohort pooling Expression matrices never combined; Z-scoring always intra-cohort
Strict I/O options(warn = 2) — any warning is a fatal error
Skip/force pattern Scripts check for existing outputs; FORCE_RERUN=TRUE to override
Anti-hard-code check Script 16 verifies no manuscript number was typed manually
Leakage-proof Training (SCAN-B) and validation cohorts are never mixed
No coefficient refitting Validation cohorts use training weights only

Key Output Artefacts

Artefact Path Description
CorePAM_weights.csv results/corepam/ 24 genes with Cox elastic-net weights
CorePAM_model.rds results/corepam/ Fitted glmnet model (git-ignored; regenerated by script 05)
selected_CorePAM_summary.json results/corepam/ Derivation metadata (C-index, genes, lambda)
pareto_df_cindex_oof.csv results/corepam/ Pareto frontier: gene count vs. OOF C-index
Table3_*.csv results/main/ Survival performance by cohort (HR, C-index, events)
meta_survival_summary.csv results/main/ Random-effects meta-analysis results
pCR_results_by_cohort.csv results/pcr/ Logistic regression per pCR cohort
meta_pCR_results.csv results/pcr/ pCR meta-analysis (OR, I2)

CorePAM Score Formula

For a given sample in cohort c:

G_present = CorePAM genes ∩ genes available in cohort c
z_i       = intra-cohort Z-score for gene i
score     = Σ(w_i · z_i) / Σ|w_i|     (over G_present)
score_z   = scale(score)                (for HR per 1-SD)

Weights (w_i) are fixed from training. Score direction is established in SCAN-B and never re-inverted per cohort.


Data Sources

All data are publicly available:


Troubleshooting

Problem Solution
Package installation fails Run source("INSTALL.R") in a clean R session
Download times out Re-run 01_download_raw_data.R; the skip/force pattern resumes from where it stopped
"Output already exists" Set FORCE_RERUN=TRUE environment variable to re-execute
Warning treated as error This is by design (options(warn=2)). Investigate the warning — it may indicate a data issue
Memory error Ensure >= 16 GB RAM. Close other applications before running preprocessing scripts

Citation

If you use this work, please cite:

Botan RN, Sousa JB. CorePAM: a 24-gene PAM50-derived expression score with cross-platform external validation for breast cancer prognosis. Breast Cancer Res. 2026 (under review).

See also CITATION.cff for machine-readable citation metadata.


Contact

  • Rafael de Negreiros Botanoncologista@gmail.com
  • Faculty of Medicine, University of Brasilia (UnB), Brazil

License

Analysis code: MIT License. Data are from public repositories (GEO, GDC, cBioPortal) under their respective terms of use.

About

CorePAM: a PAM50-derived minimum gene expression score for breast cancer prognosis

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages

Morty Proxy This is a proxified and sanitized view of the page, visit original site.