OmniAgeR 0.99.4
The OmniAgeR package provides two primary, high-level interfaces: epiMarker():
For calculating a comprehensive suite of aging-related clocks (chronological,
biological, mitotic, etc.). For advanced users or specific applications, the
package also provides direct access to individual clock functions (e.g.,
horvath2013Clock()) and specialized “bundle” calculators (e.g., pcClocks(),
systemsAge()) that manage complex dependencies. These tools are broadly
categorized into three main groups:
The suite of epigenetic aging clocks is particularly extensive, organized into several functional categories, including predictors for chronological age, biological age, cellular division (mitotic clocks), and gestational age.
These DNAm clocks are designed for the prediction of chronological age.
Horvath2013: (Horvath 2013) The original pan-tissue clock from 353 CpGs.Hannum: (Hannum et al. 2013) Blood-specific clock from 71 CpGs.Lin: (Lin et al. 2016) Clock based on 99 CpGs.VidalBralo: (Vidal-Bralo et al. 2016) Clock based on 8 CpGs.ZhangClock: (Zhang et al. 2019) Improved-precision clock from 514 CpGs.Horvath2018: (Horvath et al. 2018) Skin & blood clock.Bernabeu_cAge: (Bernabeu et al. 2022) Clock based on 3225 CpGs.CorticalClock: (Shireby et al. 2020) Brain cortical clock.PedBE: (McEwen et al. 2019) Pediatric buccal epithelial clock for children.CentenarianClock: (Eric Dec et al. 2023) Centenarian epigenetic clocks.Retro_age: (Ndhlovu et al. 2024) Retroelement-based clock developed on
the EPIC v1/v2 arrays.ABEC: (Lee et al. 2020) Adult blood-based EPIC clock.eABEC: (Lee et al. 2020) Extended adult blood-based EPIC clock.cABEC: (Lee et al. 2020) Common adult blood-based EPIC clock.PipekElasticNet: (Pipek et al. 2023) Pipek’s multi-tissue elastic Net
epigenetic clock (239 CpGs).PipekFilteredh: (Pipek et al. 2023) Pipek’s filtered horvath epigenetic
clock (272 CpGs).PipekRetrainedh: (Pipek et al. 2023) Pipek’s retrained horvath epigenetic
clock (308 CpGs).WuClock: (Wu et al. 2019) Wu’s Epigenetic Clock for Pediatric age
estimation.Weidner: (Weidner et al. 2014) Calculate weidner epigenetic age (3 CpGs).IntrinClock: (Tomusiak et al. 2024) Calculates the intrinsic cellular age.Garagnani: (Garagnani et al. 2012) The Garagnani ELOVL2-based epigenetic
age score(1 CpG).PCHorvath2013, PCHorvath2018, PCHannum: (Higgins-Chen et al. 2022)
Computationally-bolstered versions of the original clocks. These PC clocks
are retrained using principal components (PCs) derived from a large CpG set
to minimize technical noise and improve reliabilityThese advanced clocks are designed to capture biological aging rather than chronological time, often showing stronger associations with health outcomes and mortality.
Zhang10: (Zhang et al. 2017) 10-CpG clock associated with mortality.PhenoAge: (Levine et al. 2018) Predicts phenotypic age from 513 CpGs.DunedinPACE: (Belsky et al. 2022) Quantifies the pace of biological aging.GrimAge1: The original GrimAge clock (Lu et al. 2019).GrimAge2: (Lu et al. 2022) Updated composite biomarker of mortality risk.PCPhenoAge, PCGrimAge1: (Higgins-Chen et al. 2022)
Computationally-bolstered PC versions of the PhenoAge and GrimAge1 clocks,
retrained on principal components for enhanced reliability.DNAmFitAge: (McGreevy et al. 2023) Biological age indicator incorporating
DNAmGrimAge and 3 DNAm-based physical fitness markers.IC_Clock: (Fuentealba et al. 2025) The intrinsic capacity (IC) clock based
on 91 CpGs.SystemsAge: (Sehgal et al. 2025) The systems age and 11 system-specific
scores.This category groups biomarkers that measure two key forms of cellular aging: cell proliferation (mitotic clocks) and telomere attrition (DNAmTL).
A specialized set of clocks that measure cell division history or stem cell divisions.
epiTOC1: (Yang et al. 2016) Average beta value of 385 promoter CpGs.epiTOC2: (Teschendorff et al. 2020) Estimates stem cell divisions using a
dynamic model.epiTOC3: Estimates stem cell divisions based on unmethylated population
doubling associated CpGs.stemTOCvitro: (Zhu et al. 2024) The 0.95 upper quantile of 629
stemTOCvitro CpGs (promoter CpGs unmethylated in fetal tissue that
hypermethylate with population-doublings).stemTOC: (Zhu et al. 2024) The 0.95 upper quantile of 371 stemTOC CpGs,
filtered for in-vivo hypermethylation with age.RepliTali: (Endicott et al. 2022) Based on 87 population doubling
associated hypomethylated CpGs.HypoClock: (Teschendorff et al. 2020) Based on hypomethylation at 678
solo-WCGW sites.EpiCMIT_hyper: (Duran-Ferrer et al. 2020) Average beta value of 184
age-associated hypermethylated CpGs.EpiCMIT_hypo: (Duran-Ferrer et al. 2020) Average beta value of 1164
age-associated hypomethylated CpGs.DNAmTL: (Lu AT et al. 2019) Calculates the Leukocyte telomere length.PCDNAmTL: (Lu AT et al. 2019; Higgins-Chen et al. 2022)
A computationally-bolstered “PC” version of the original DNAmTL clock. This
clock is retrained using principal components (PCs) derived from a large CpG
set to minimize technical noise and improve reliability.A new generation of clocks developed to reflect potential causal drivers of aging.
CausalAge, DamAge, AdaptAge: (Ying et al. 2024) Three clocks derived
from a causality-enriched model. They dissect aging into distinct components:
‘Causal’ (CausalAge), ‘Damage’ (DamAge), and Adaptation’ (AdaptAge).StocH, StocP, StocZ: (Tong et al. 2024) Stochastic analogues of the
Horvath, PhenoAge, and Zhang clocks, trained on artificial cohorts to quantify
the stochastic component of epigenetic aging.These clocks are designed to measure aging in specific cell types or tissues, accounting for cellular heterogeneity.
Neu-In, Glia-In: (Tong et al. 2024) Intrinsic clocks for neurons,
and glia.Neu-Sin, Glia-Sin, Hep: (Tong et al. 2024) Semi-intrinsic clocks for
neurons, glia, and hepatocytesThis collection includes DNAm clocks designed to predict gestational age at birth.
BohlinGA: (Bohlin et al. 2016) The Bohlin Gestational Age.EPICGA: (Haftorn et al. 2021) The EPIC Gestational Age.LeeGA: (Lee et al. 2019) A list (LeeControl, LeeRobust, LeeRefinedRobust).KnightGA: (Knight et al. 2016) The Knight Gestational Age.MayneGA: (Mayne et al. 2017) The Mayne Placental Gestational Age.EnsembleAge: (Haghani et al. 2025) The multi-clock framework
implementation. This includes mouse-specific estimators
(EnsembleAgeMouse_Dynamic and EnsembleAgeMouse_Static) and a
cross-species (EnsembleAgeMouse_HumanMouse) predictor applicable to both
humans and mice
UniversalPanMammalianClocks: (Lu et al. 2023) The three pan-tissue clocks
(Clock 1, 2, 3) applicable across all mammalian tissues.
PanMammalianBlood: (Lu et al. 2023) The two blood-specific pan-mammalian
clocks (Clock 2, 3).
PanMammalianSkin: (Lu et al. 2023) The two skin-specific pan-mammalian
clocks (Clock 2, 3).
In addition to DNAm-based models, the package implements cutting-edge transcriptomic (RNA-seq) clocks:
sc-ImmuAging: A single-cell, immune-cell-type-specific aging clock.Brain_CT_clock: A brain-cell-type-specific aging clock based on
Single-Nuclei Transcriptomics.PASTA: A robust, multi-tissue transcriptomic clock based on a novel
age-shift learning strategy. It utilizes rank-normalization to ensure broad
applicability across heterogeneous datasets, including bulk RNA-seq,
single-cell pseudobulks, and microarrays.Besides, OmniAgeR includes functions to compute several other important
surrogate markers associated with aging, lifestyle, and health status from DNAm
data.
CRP: Calculates a score for C-reactive protein (CRP) levels, a marker of
inflammation.
CHIP: Calculates scores for Clonal Hematopoiesis of Indeterminate
Potential (CHIP).
IL6: Computes a DNA methylation (DNAm) surrogate score for Interleukin-6
(IL-6) protein levels.
EpiScores: Computes the 109 validated epigenetic scores (EpiScores) that
serve as DNA methylation-based proxies for the levels of circulating plasma
proteins as defined by Gadd et al. (2022).
McCartneyTrait: Computes epigenetic surrogate scores for 10 different
complex traits and biomarkers based on blood methylation models. Traits include:
BMI, Smoking (pack-years), Alcohol (units/week), Education (years),
Total_cholesterol, HDL_cholesterol, LDL_cholesterol, Total_HDL_ratio,
WHR (Waist-to-Hip Ratio), and Body_fat_Perc.
OmniAgeR provides a suite of tools for disease risk assessment, including a
DNA methylation-based smoking index derived from 1,501 CpG sites, as well as
specialized scores for cancer risks. These tools leverage robust epigenetic
signatures to quantify environmental exposures and clinical outcomes.
CompSmokeIndex: Computes a DNAm-based Smoking Index that correlates with
cancer risk across various tissues.HepatoXuRisk: Calculate HepatoXu ctDNA Methylation Scores for
Hepatocellular CarcinomaThe OmniAgeR package also provides a DNA Methylation Cell-Type Fraction (CTF)
clock (implemented as dnamCTFClock), which was trained on a large-scale NSPT
dataset comprising more than 3,500 blood samples. The clock incorporates 12
immune cell types, estimated using the EpiDISH algorithm, to model aging based
on cell-type composition.
| Clock Name | Category | Calculator / Function |
|---|---|---|
Horvath2013 |
Chronological | epiMarker(),horvath2013Clock() |
Hannum |
Chronological | epiMarker(),hannumClock() |
Lin |
Chronological | epiMarker(),linClock() |
VidalBralo |
Chronological | epiMarker(),vidalBraloClock() |
ZhangClock |
Chronological | epiMarker(),zhangClock() |
Horvath2018 |
Chronological | epiMarker(),horvath2018Clock() |
Bernabeu_cAge |
Chronological | epiMarker(),bernabeuCAge() |
CorticalClock |
Chronological | epiMarker(),corticalClock() |
PedBE |
Chronological | epiMarker(),pedBEClock() |
CentenarianClock |
Chronological | epiMarker(),centenarianClock() |
Retro_age |
Chronological | epiMarker(),retroAge() |
ABEC |
Chronological | epiMarker(),leeABEC() |
eABEC |
Chronological | epiMarker(),leeExtendedABEC() |
cABEC |
Chronological | epiMarker(),leeCommonABEC() |
PipekElasticNet |
Chronological | epiMarker(),pipekElasticNet() |
PipekFilteredh |
Chronological | epiMarker(),pipekFilteredh() |
PipekRetrainedh |
Chronological | epiMarker(),pipekRetrainedh() |
WuClock |
Chronological | epiMarker(),wuClock() |
Weidner |
Chronological | epiMarker(),weidnerClock() |
IntrinClock |
Chronological | epiMarker(),intrinClock() |
Garagnani |
Chronological | epiMarker(),garagnaniClock() |
Zhang10 |
Biological | epiMarker(),zhang10() |
PhenoAge |
Biological | epiMarker(),phenoAge() |
DunedinPACE |
Biological | epiMarker(),dunedinPACE() |
GrimAge1 |
Biological | epiMarker(),grimAge1() |
GrimAge2 |
Biological | epiMarker(),grimAge2() |
DNAmFitAge |
Biological | epiMarker(),dnamFitAge() |
IC_Clock |
Biological | epiMarker(),icClock() |
SystemsAge |
Biological | epiMarker(),systemsAge() |
epiTOC1 |
Mitotic | epiMarker(),epiTOC1() |
epiTOC2 |
Mitotic | epiMarker(),epiTOC2() |
epiTOC3 |
Mitotic | epiMarker(),epiTOC3() |
stemTOC |
Mitotic | epiMarker(),stemTOC() |
stemTOCvitro |
Mitotic | epiMarker(),stemTOCvitro() |
RepliTali |
Mitotic | epiMarker(),repliTali() |
HypoClock |
Mitotic | epiMarker(),hypoClock() |
EpiCMIT_hyper, EpiCMIT_hypo |
Mitotic | epiMarker(),epiCMIT() |
DNAmTL |
Telomere length | epiMarker(),dnamTL() |
PCHorvath2013,PCHorvath2018, PCHannum, PCPhenoAge, PCGrimAge1, PCDNAmTL |
Chronological/Biological/Telomere length | epiMarker(),pcClocks() |
CausalAge,DamAge,AdaptAge |
Causal | epiMarker(),causalClock() |
StocH,StocP,StocZ |
Causal | epiMarker(),stochClocks() |
Neu-In,Glia-In,Neu-Sin,Glia-Sin,Hep |
Cell-Type Specific | epiMarker(),ctsClocks() |
BohlinGA |
Gestational | epiMarker(),bohlinGa() |
EPICGA |
Gestational | epiMarker(),epicGa() |
LeeGA |
Gestational | epiMarker(),LeeGa() |
KnightGA |
Gestational | epiMarker(),knightGa() |
MayneGA |
Gestational | epiMarker(),mayneGa() |
EnsembleAge_HumanMouse |
Mouse & Human | epiMarker(),ensembleAge() |
EnsembleAge_Static |
Mouse & Human | epiMarker(),ensembleAge() |
EnsembleAge_Dynamic |
Mouse & Human | epiMarker(),ensembleAge() |
UniversalPanMammalianClocks |
PanMammalian | epiMarker(),universalPanMammalianClocks() |
PanMammalianBlood |
PanMammalian | epiMarker(),panMammalianBlood() |
PanMammalianSkin |
PanMammalian | epiMarker(),panMammalianSkin() |
DNAm_CTF_Clock |
Cell-Type Fraction Clock | epiMarker(),dnamCTFClock() |
| Clock Name | Category | Calculator / Function |
|---|---|---|
scImmuAging |
Immune-cell-type-specific | scImmuAging() |
Brain_CT_Clock |
Brain-cell-type-specific | brainCtClock() |
PASTA |
Multi-tissue | pastaScores() |
| Clock Name | Target | Calculator / Function |
|---|---|---|
CRP |
CRP/intCRP score | epiMarker(), compCRP() |
CHIP |
CHIP score | epiMarker(), compCHIP() |
IL6 |
IL6 score | epiMarker(), compIL6() |
EpiScores |
109 validated epigenetic scores | epiMarker(), compEpiScores() |
CompSmokeIndex |
Smoking Index | epiMarker(), compSmokeIndex() |
HepatoXuRisk |
Hepatocellular Carcinoma Risk | epiMarker(), hepatoXuRisk() |
SmokeIndex |
Smoking Index | epiMarker(), compSmokeIndex() |
McCartney_Trait |
Epigenetic surrogate scores for 10 different complex traits | epiMarker(), mcCartneyTrait() |
This is an Illumina 450k dataset encompassing 21 normal lung tissue samples and 35 lung carcinoma in situ (LCIS) samples, of which 22 progressed to an invasive lung cancer (LC). Here we explore the correlation between mitotic age and cancer state with linear model, treating N, LCIS, and LC as ordinal variable (1,2,3) and adjusting for age.
library(OmniAgeR)
library(ggplot2)
library(patchwork)
library(ggpubr)
lungInv <- loadOmniAgeRdata(
"omniager_lung_inv",
verbose = FALSE
)
## see ?OmniAgeRData and browseVignettes('OmniAgeRData') for documentation
## loading from cache
lungInvM <- lungInv$bmiq_m
phenoDf <- lungInv$PhenoTypes
my_comparisons <- list(c("N\nN=21", "LCIS\nN=13"), c("LCIS\nN=13", "LCIS->LC\nN=22"))
table(phenoDf$Group)
##
## LCIS\nN=13 LCIS->LC\nN=22 N\nN=21
## 13 22 21
## Check available epigenetic clocks
listEpiMarker()
## $mitotic
## [1] "epiTOC1" "epiTOC2" "epiTOC3" "stemTOCvitro"
## [5] "stemTOC" "RepliTali" "HypoClock" "EpiCMIT_Hyper"
## [9] "EpiCMIT_Hypo"
##
## $dnamtl
## [1] "DNAmTL" "PCDNAmTL"
##
## $chronological
## [1] "Horvath2013" "Hannum" "Lin" "VidalBralo"
## [5] "ZhangClock" "Horvath2018" "Bernabeu_cAge" "CorticalClock"
## [9] "PedBE" "CentenarianClock" "Retro_age" "ABEC"
## [13] "eABEC" "cABEC" "PipekElasticNet" "PipekFilteredh"
## [17] "PipekRetrainedh" "WuClock" "Weidner" "IntrinClock"
## [21] "Garagnani" "PCHorvath2013" "PCHorvath2018" "PCHannum"
##
## $biological
## [1] "Zhang10" "PhenoAge" "DunedinPACE" "GrimAge1" "GrimAge2"
## [6] "PCPhenoAge" "PCGrimAge1" "DNAmFitAge" "IC_Clock" "SystemsAge"
##
## $causal
## [1] "CausalAge" "DamAge" "AdaptAge"
##
## $cellTypeSpecific
## [1] "Neu-In" "Neu-Sin" "Glia-In" "Glia-Sin" "Hep"
##
## $stochastic
## [1] "StocH" "StocZ" "StocP"
##
## $gestationalAge
## [1] "BohlinGA" "EPICGA" "KnightGA" "LeeGA" "MayneGA"
##
## $surrogateBiomarkers
## [1] "CRP" "CHIP" "IL6" "EpiScores"
##
## $traitPred
## [1] "McCartneyTrait"
##
## $diseaseRisk
## [1] "SmokeIndex" "HepatoXuRisk"
##
## $crossSpecies
## [1] "EnsembleAge_HumanMouse" "EnsembleAge_Static"
## [3] "EnsembleAge_Dynamic" "UniversalPanMammalianClocks"
## [5] "PanMammalianBlood" "PanMammalianSkin"
Mitotic age estimation of all the clocks is implemented in a general function EpiMitClocks. The required input is a DNAm beta value matrix with rows labeling Illumina 450k/EPIC CpGs and columns labeling samples.
epiMarkerRes <- epiMarker(
betaM = lungInvM,
clockNames = "mitotic",
chronAge = phenoDf$Age,
minCoverage = 0,
verbose = FALSE
)
## see ?OmniAgeRData and browseVignettes('OmniAgeRData') for documentation
## loading from cache
## see ?OmniAgeRData and browseVignettes('OmniAgeRData') for documentation
## loading from cache
## see ?OmniAgeRData and browseVignettes('OmniAgeRData') for documentation
## loading from cache
## see ?OmniAgeRData and browseVignettes('OmniAgeRData') for documentation
## loading from cache
## see ?OmniAgeRData and browseVignettes('OmniAgeRData') for documentation
## loading from cache
## see ?OmniAgeRData and browseVignettes('OmniAgeRData') for documentation
## loading from cache
## see ?OmniAgeRData and browseVignettes('OmniAgeRData') for documentation
## loading from cache
## see ?OmniAgeRData and browseVignettes('OmniAgeRData') for documentation
## loading from cache
rm(lungInvM)
phenoDf$epiTOC1 <- epiMarkerRes$epiTOC1
phenoDf$epiTOC2 <- epiMarkerRes$epiTOC2$irS
phenoDf$epiTOC3 <- epiMarkerRes$epiTOC3$irS
phenoDf$stemTOCvitro <- epiMarkerRes$stemTOCvitro
phenoDf$stemTOC <- epiMarkerRes$stemTOC
phenoDf$HypoClock <- epiMarkerRes$HypoClock
phenoDf$RepliTali <- epiMarkerRes$RepliTali
phenoDf$EpiCMIT_Hyper <- epiMarkerRes$EpiCMIT_Hyper
phenoDf$EpiCMIT_Hypo <- epiMarkerRes$EpiCMIT_Hypo
g <- list()
for (i in 1:9) {
tempDf <- data.frame("Group" = phenoDf$Group, "Age" = phenoDf$Age, "num" = phenoDf$num, "score" = phenoDf[, i + 3])
y <- summary(lm(tempDf$score ~ tempDf$num + tempDf$Age))$coefficients[2, 4]
g[[i]] <- ggplot(tempDf, aes(x = Group, y = score, fill = Group)) +
guides(fill = "none") +
geom_boxplot() +
theme_bw() +
scale_x_discrete(limits = c("N\nN=21", "LCIS\nN=13", "LCIS->LC\nN=22")) +
stat_compare_means(method = "wilcox.test", comparisons = my_comparisons, size = 4) +
xlab("") +
ylab(colnames(phenoDf)[i + 3]) +
annotate("text", x = 2, y = max(tempDf$score) * 0.9, label = paste0("P(Age-adjusted)=", signif(y, 2)), size = 4) +
theme(
axis.title = element_text(size = 11),
axis.text = element_text(size = 11)
)
}
ggpubr::ggarrange(plotlist = g, nrow = 3, ncol = 3)
The epigenetic age of 50 normal blood samples was estimated from their Illumina 450k methylation profiles using both the Horvath and Zhang epigenetic clocks.
library(OmniAgeR)
library(ggplot2)
library(patchwork)
library(ggpubr)
hannumExample <- loadOmniAgeRdata(
"omniager_hannum_example",
verbose = FALSE
)
## see ?OmniAgeRData and browseVignettes('OmniAgeRData') for documentation
## loading from cache
hannumBmiqM <- hannumExample[[1]]
phenoTypesHannum <- hannumExample[[2]]
age <- phenoTypesHannum$Age
sex <- ifelse(phenoTypesHannum$Sex == "F", "Female", "Male")
epiMarkerOut <- epiMarker(hannumBmiqM,
clockNames = c("Horvath2013", "ZhangClock"),
minCoverage = 0, verbose = FALSE
)
## see ?OmniAgeRData and browseVignettes('OmniAgeRData') for documentation
## loading from cache
## see ?OmniAgeRData and browseVignettes('OmniAgeRData') for documentation
## loading from cache
gp <- list()
for (i in seq_along(epiMarkerOut)) {
plot_df <- data.frame(ActualAge = phenoTypesHannum$Age, PredictedAge = epiMarkerOut[[i]])
cor_test_result <- cor.test(plot_df$ActualAge, plot_df$PredictedAge)
correlation <- cor_test_result$estimate
p_value <- cor_test_result$p.value
mae <- mean(abs(plot_df$PredictedAge - plot_df$ActualAge))
p_value_formatted <- ifelse(p_value < 0.001,
formatC(p_value, format = "e", digits = 2),
round(p_value, 3)
)
annotation_text <- paste0(
"R = ", round(correlation, 3), "\n",
"P = ", p_value_formatted, "\n",
"MAE = ", round(mae, 2)
)
gp[[i]] <- ggplot(data = plot_df, aes(x = ActualAge, y = PredictedAge)) +
geom_point(color = "steelblue", size = 3, alpha = 0.8) +
geom_smooth(method = "lm", color = "black", se = FALSE) +
annotate("text",
x = min(plot_df$ActualAge, na.rm = TRUE),
y = max(plot_df$PredictedAge, na.rm = TRUE),
label = annotation_text,
hjust = 0,
vjust = 1, size = 5
) +
labs(
title = NULL,
x = "Chronological Age",
y = paste0("Predicted Age(", c("Horvath2013", "ZhangClock")[i], ")")
) +
theme_bw() +
theme(
plot.title = element_text(hjust = 0.5, size = 16, face = "bold"),
plot.subtitle = element_text(hjust = 0.5, size = 12),
axis.title = element_text(size = 14),
axis.text = element_text(size = 12)
)
}
ggpubr::ggarrange(plotlist = gp, nrow = 1, ncol = 2)
## `geom_smooth()` using formula = 'y ~ x'
## `geom_smooth()` using formula = 'y ~ x'
A small demonstration dataset containing three samples, used to illustrate how to predict the gestational age of samples using DNAm Gestational Age Clocks.
library(OmniAgeR)
library(ggplot2)
library(patchwork)
library(ggpubr)
gaExample <- loadOmniAgeRdata(
"omniager_ga_example",
verbose = FALSE
)
## see ?OmniAgeRData and browseVignettes('OmniAgeRData') for documentation
## loading from cache
gaM <- gaExample[[1]]
phenoTypesGa <- gaExample[[2]]
epiGA <- epiMarker(gaM,
clockNames = c("KnightGA", "MayneGA"),
minCoverage = 0, verbose = FALSE
)
## see ?OmniAgeRData and browseVignettes('OmniAgeRData') for documentation
## loading from cache
## see ?OmniAgeRData and browseVignettes('OmniAgeRData') for documentation
## loading from cache
gp <- list()
for (i in seq_along(epiGA)) {
plot_df <- data.frame(Gestational_Age = phenoTypesGa$age, PredictedAge = epiGA[[i]])
cor_test_result <- cor.test(plot_df$Gestational_Age, plot_df$PredictedAge)
correlation <- cor_test_result$estimate
p_value <- cor_test_result$p.value
mae <- mean(abs(plot_df$PredictedAge - plot_df$Gestational_Age))
p_value_formatted <- ifelse(p_value < 0.001,
formatC(p_value, format = "e", digits = 2),
round(p_value, 3)
)
annotation_text <- paste0(
"R = ", round(correlation, 3), "\n",
"P = ", p_value_formatted, "\n",
"MAE = ", round(mae, 2)
)
gp[[i]] <- ggplot(data = plot_df, aes(x = Gestational_Age, y = PredictedAge)) +
geom_point(color = "steelblue", size = 3, alpha = 0.8) +
geom_smooth(method = "lm", color = "black", se = FALSE) +
annotate("text",
x = min(plot_df$Gestational_Age, na.rm = TRUE),
y = max(plot_df$PredictedAge, na.rm = TRUE),
label = annotation_text,
hjust = 0,
vjust = 1, size = 5
) +
labs(
title = NULL,
x = "Gestational Age(weeks)",
y = paste0("Predicted Age(", c("Knight GA", "Mayne GA")[i], ", weeks)")
) +
theme_bw() +
theme(
plot.title = element_text(hjust = 0.5, size = 16, face = "bold"),
plot.subtitle = element_text(hjust = 0.5, size = 12),
axis.title = element_text(size = 14),
axis.text = element_text(size = 12)
)
}
ggpubr::ggarrange(plotlist = gp, nrow = 1, ncol = 2)
## `geom_smooth()` using formula = 'y ~ x'
## `geom_smooth()` using formula = 'y ~ x'
In this example, we showcase the application of the cell-type-specific clock, scImmuAging, to a PBMC scRNA-seq dataset. The dataset includes 20 samples, profiled to contain only CD4+ and CD8+ T cells.
library(OmniAgeR)
library(Seurat)
library(glmnet)
library(ggplot2)
library(patchwork)
library(ggpubr)
#library(Seurat)
seuratObj <- loadOmniAgeRdata(
"omniager_yazar_cd4t_cd8t_example",
verbose = FALSE
)
scImmuAgingOut <- scImmuAging(seuratObj, c("CD4T", "CD8T"))
sc_gp <- list()
for (i in seq_along(scImmuAgingOut)) {
plot_df <- data.frame(ActualAge = scImmuAgingOut[[i]]$donor$age, PredictedAge = scImmuAgingOut[[i]]$donor$predicted)
cor_test_result <- cor.test(plot_df$ActualAge, plot_df$PredictedAge)
correlation <- cor_test_result$estimate
p_value <- cor_test_result$p.value
mae <- mean(abs(plot_df$PredictedAge - plot_df$ActualAge))
p_value_formatted <- ifelse(p_value < 0.001,
formatC(p_value, format = "e", digits = 2),
round(p_value, 3)
)
annotation_text <- paste0(
"R = ", round(correlation, 3), "\n",
"P = ", p_value_formatted, "\n",
"MAE = ", round(mae, 2)
)
sc_gp[[i]] <- ggplot(data = plot_df, aes(x = ActualAge, y = PredictedAge)) +
geom_point(color = "steelblue", size = 3, alpha = 0.8) +
geom_smooth(method = "lm", color = "black", se = FALSE) +
annotate("text",
x = min(plot_df$ActualAge, na.rm = TRUE),
y = max(plot_df$PredictedAge, na.rm = TRUE),
label = annotation_text,
hjust = 0,
vjust = 1,
size = 5
) +
labs(
title = c("CD4T", "CD8T")[i],
x = "Chronological Age",
y = "Predicted Age(sc-ImmuAging)"
) +
theme_bw() +
theme(
plot.title = element_text(hjust = 0.5, size = 16, face = "bold"),
plot.subtitle = element_text(hjust = 0.5, size = 12),
axis.title = element_text(size = 14),
axis.text = element_text(size = 12)
)
}
ggpubr::ggarrange(plotlist = sc_gp, nrow = 1, ncol = 2)
In this example, we showcase the application of the brain cell-type-specific aging Clocks to a brain snRNA-seq dataset. The dataset includes 15 donors, profiled to contain only Oligodendrocytes.
library(OmniAgeR)
library(Seurat)
library(glmnet)
library(ggplot2)
library(patchwork)
library(ggpubr)
library(dplyr)
brainSeurat <- loadOmniAgeRdata(
"omniager_brain_frohlich_control_example_15donors",
verbose = FALSE
)
# Define cell types of interest
cellTypes <- c("Oligodendrocytes")
# Run all three models for the specified cell types
clockResults <- brainCtClock(
seuratObj = brainSeurat,
cellTypes = cellTypes
)
# Use lapply to iterate over each data frame in the list
averagePredictionsDonor <- lapply(clockResults, function(df) {
df %>%
group_by(donorId, age, sampleType, celltype) %>%
summarise(mean_prediction = mean(prediction, na.rm = TRUE))
})
brainPlot <- list()
for (i in seq_along(averagePredictionsDonor)) {
plot_df <- data.frame(
ActualAge = averagePredictionsDonor[[i]]$age,
PredictedAge = averagePredictionsDonor[[i]]$mean_prediction
)
cor_test_result <- cor.test(plot_df$ActualAge, plot_df$PredictedAge)
correlation <- cor_test_result$estimate
p_value <- cor_test_result$p.value
mae <- mean(abs(plot_df$PredictedAge - plot_df$ActualAge))
p_value_formatted <- ifelse(p_value < 0.001,
formatC(p_value, format = "e", digits = 2),
round(p_value, 3)
)
annotation_text <- paste0(
"R = ", round(correlation, 3), "\n",
"P = ", p_value_formatted, "\n",
"MAE = ", round(mae, 2)
)
brainPlot[[i]] <- ggplot(data = plot_df, aes(x = ActualAge, y = PredictedAge)) +
geom_point(color = "steelblue", size = 3, alpha = 0.8) +
geom_smooth(method = "lm", color = "black", se = FALSE) +
annotate("text",
x = min(plot_df$ActualAge, na.rm = TRUE),
y = max(plot_df$PredictedAge, na.rm = TRUE),
label = annotation_text,
hjust = 0,
vjust = 1,
size = 4
) +
labs(
title = "Oligodendrocytes",
x = "Chronological Age",
y = paste0("Predicted Age(", c("SC", "Pseudobulk", "Bootstrap")[i], ")")
) +
theme_bw() +
theme(
plot.title = element_text(hjust = 0.5, size = 16, face = "bold"),
plot.subtitle = element_text(hjust = 0.5, size = 12),
axis.title = element_text(size = 14),
axis.text = element_text(size = 12)
)
}
ggpubr::ggarrange(plotlist = brainPlot, nrow = 1, ncol = 3)
In this example, we showcase the application of the Pasta clock to a single-nuclei RNA-seq dataset from the middle temporal gyrus (MTG) (Gabitto et al., 2024). The dataset includes 46 healthy donors and is filtered to contain extratelencephalic projecting glutamatergic cortical neurons.
# Load required libraries
library(OmniAgeR)
library(Seurat)
library(glmnet)
library(magrittr) # For %>% pipe
library(ggplot2)
library(patchwork)
library(ggpubr) # For simplified plot annotations
seu <- loadOmniAgeRdata(
"omniager_seu_gabitto_2024_filtered",
verbose = FALSE
)
# Extract and clean chronological age from metadata
seu$age <- seu$development_stage %>%
gsub("-year.*", "", .) %>%
gsub("-", " ", .) %>%
gsub("80 year old and over stage", "85", .)
# Create pseudobulk samples, Pseudobulk construction may follow Salignon et al.
# or be performed using alternative approaches as appropriate
set.seed(42)
seuBulk <- makePseudobulksPasta(
seu,
poolBy = c("cell_type", "age"),
chunkSize = 512,
verbose = FALSE
)
# Extract the log-normalized expression matrix for prediction
lognormMatrix <- GetAssayData(seuBulk, assay = "RNA", layer = "data")
lognormMatrix <- as.matrix(lognormMatrix)
# Extract the corresponding metadata for the new pseudobulk samples
seuBulkMeta <- seuBulk[[c("chunkSize", "cell_type", "age")]]
seuBulkMeta$age <- as.numeric(seuBulkMeta$age)
# Apply the PASTA clock
# filter_genes = TRUE: Selects only the genes required by the PASTA model.
# rank_norm = TRUE: Applies the rank-normalization required by PASTA.
pastaRes <- pastaScores(lognormMatrix, filterGenes = TRUE, rankNorm = TRUE)
# Prepare the data frame for plotting
plot_df <- data.frame(
ActualAge = as.numeric(seuBulk$age),
Prediction = as.numeric(pastaRes$PASTA)
)
# Create the scatter plot
ggplot(data = plot_df, aes(x = ActualAge, y = Prediction)) +
geom_point(color = "steelblue", size = 3, alpha = 0.8) +
geom_smooth(method = "lm", color = "black", se = FALSE) +
ggpubr::stat_cor(
method = "pearson",
label.x.npc = "left",
label.y.npc = "top",
hjust = 0,
size = 5
) +
labs(
title = NULL,
x = "Chronological Age",
y = "PASTA Score"
) +
theme_bw() +
theme(
plot.title = element_text(hjust = 0.5, size = 16, face = "bold"),
axis.title = element_text(size = 14),
axis.text = element_text(size = 12),
legend.position = "none"
)
Here, we use DNAm data to calculate the CRP score and CHIP score.
library(OmniAgeR)
hannumBmiqM <- loadOmniAgeRdata(
"omniager_hannum_example",
verbose = FALSE
)[[1]]
## see ?OmniAgeRData and browseVignettes('OmniAgeRData') for documentation
## loading from cache
crpRes <- compCRP(hannumBmiqM)
## [OmniAgeR] Retrieving resource: omniager_crp_cpg
## see ?OmniAgeRData and browseVignettes('OmniAgeRData') for documentation
## loading from cache
## [OmniAgeR] Successfully loaded 'omniager_crp_cpg'.
## [CRP] Found: 1764, Required: 1765 (Coverage: 99.9%)
## [intCRP] Found: 62, Required: 62 (Coverage: 100.0%)
print(lapply(crpRes, head, 5))
## $CRP
## GSM990532 GSM990292 GSM989979 GSM989900 GSM990054
## -0.4065040 0.3002201 -0.1465114 -0.1490234 -0.3857877
##
## $intCRP
## GSM990532 GSM990292 GSM989979 GSM989900 GSM990054
## -0.29625111 0.23775122 -0.06492197 0.03861159 -0.46205741
chipRes <- compCHIP(hannumBmiqM)
## [OmniAgeR] Retrieving resource: omniager_chip_cpg
## see ?OmniAgeRData and browseVignettes('OmniAgeRData') for documentation
## loading from cache
## [OmniAgeR] Successfully loaded 'omniager_chip_cpg'.
## [AnyCHIP] Found: 9566, Required: 9615 (Coverage: 99.5%)
## [DNMT3A] Found: 5961, Required: 5990 (Coverage: 99.5%)
## [TET2] Found: 5611, Required: 5633 (Coverage: 99.6%)
## [ASXL1] Found: 6025, Required: 6078 (Coverage: 99.1%)
print(lapply(chipRes, head, 5))
## $AnyCHIP
## GSM990532 GSM990292 GSM989979 GSM989900 GSM990054
## -0.503068906 -0.359947191 0.006808985 -0.648675130 0.353746991
##
## $DNMT3A
## GSM990532 GSM990292 GSM989979 GSM989900 GSM990054
## -1.5686495 -0.8673509 -0.1098401 -0.3111652 1.1811087
##
## $TET2
## GSM990532 GSM990292 GSM989979 GSM989900 GSM990054
## -0.1877774 -0.5414346 0.2673744 -0.5044092 0.1782826
##
## $ASXL1
## GSM990532 GSM990292 GSM989979 GSM989900 GSM990054
## -0.1334423 -0.5384459 0.0903360 -0.5016612 0.1762066
library(OmniAgeR)
# 1. Get probes for a specific chronological aging predictor
chronologicalProbes <- getMarkerWeights(clockNames = "Horvath2013")
## see ?OmniAgeRData and browseVignettes('OmniAgeRData') for documentation
## loading from cache
print(head(chronologicalProbes$Horvath2013))
## probe coef
## 1 (Intercept) 0.695507258
## 2 cg00075967 0.129336610
## 3 cg00374717 0.005017857
## 4 cg00864867 1.599764050
## 5 cg00945507 0.056852418
## 6 cg01027739 0.102862854
We apply the DNAm Cell-type Fraction (CTF) Clock to 50 blood samples (EPIC array) from the TZH cohort to predict chronological age.
library(OmniAgeR)
library(randomForest)
## randomForest 4.7-1.2
## Type rfNews() to see new features/changes/bug fixes.
##
## Attaching package: 'randomForest'
## The following object is masked from 'package:ggplot2':
##
## margin
library(ggplot2)
library(patchwork)
library(ggpubr)
tzhExample <- loadOmniAgeRdata(
"omniager_tzh_example_ctf",
verbose = FALSE
)
## see ?OmniAgeRData and browseVignettes('OmniAgeRData') for documentation
## downloading 1 resources
## retrieving 1 resource
## loading from cache
phenoTypesTzh <- tzhExample[[1]]
tzhFracM <- tzhExample[[2]]
dnamCTFClockOut <- dnamCTFClock(ctfM = tzhFracM)
## [OmniAgeR] Retrieving resource: omniager_dnam_ctf_model
## see ?OmniAgeRData and browseVignettes('OmniAgeRData') for documentation
## downloading 1 resources
## retrieving 1 resource
## loading from cache
## [OmniAgeR] Successfully loaded 'omniager_dnam_ctf_model'.
plot_df <- data.frame(ActualAge = phenoTypesTzh$Age, PredictedAge = dnamCTFClockOut)
cor_test_result <- cor.test(plot_df$ActualAge, plot_df$PredictedAge)
correlation <- cor_test_result$estimate
p_value <- cor_test_result$p.value
mae <- mean(abs(plot_df$PredictedAge - plot_df$ActualAge))
p_value_formatted <- ifelse(p_value < 0.001,
formatC(p_value, format = "e", digits = 2),
round(p_value, 3)
)
annotation_text <- paste0(
"R = ", round(correlation, 3), "\n",
"P = ", p_value_formatted, "\n",
"MAE = ", round(mae, 2)
)
ggplot(data = plot_df, aes(x = ActualAge, y = PredictedAge)) +
geom_point(color = "steelblue", size = 3, alpha = 0.8) +
geom_smooth(method = "lm", color = "black", se = FALSE) +
annotate("text",
x = min(plot_df$ActualAge, na.rm = TRUE),
y = max(plot_df$PredictedAge, na.rm = TRUE),
label = annotation_text,
hjust = 0,
vjust = 1, size = 5
) +
labs(
title = NULL,
x = "Chronological Age",
y = paste0("Predicted Age(DNAm_CTF)")
) +
theme_bw() +
theme(
plot.title = element_text(hjust = 0.5, size = 16, face = "bold"),
plot.subtitle = element_text(hjust = 0.5, size = 12),
axis.title = element_text(size = 14),
axis.text = element_text(size = 12)
)
## `geom_smooth()` using formula = 'y ~ x'
# ggpubr::ggarrange(plotlist = gp, nrow = 1, ncol = 1)
## R version 4.6.0 RC (2026-04-17 r89917)
## Platform: x86_64-pc-linux-gnu
## Running under: Ubuntu 24.04.4 LTS
##
## Matrix products: default
## BLAS: /home/biocbuild/bbs-3.23-bioc/R/lib/libRblas.so
## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.12.0 LAPACK version 3.12.0
##
## locale:
## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
## [3] LC_TIME=en_GB LC_COLLATE=C
## [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
## [7] LC_PAPER=en_US.UTF-8 LC_NAME=C
## [9] LC_ADDRESS=C LC_TELEPHONE=C
## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
##
## time zone: America/New_York
## tzcode source: system (glibc)
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] randomForest_4.7-1.2 OmniAgeRData_0.99.3 ggpubr_0.6.3
## [4] patchwork_1.3.2 ggplot2_4.0.3 OmniAgeR_0.99.4
## [7] BiocStyle_2.40.0
##
## loaded via a namespace (and not attached):
## [1] RcppAnnoy_0.0.23 splines_4.6.0 later_1.4.8
## [4] filelock_1.0.3 tibble_3.3.1 polyclip_1.10-7
## [7] preprocessCore_1.74.0 fastDummies_1.7.6 lifecycle_1.0.5
## [10] httr2_1.2.2 rstatix_0.7.3 globals_0.19.1
## [13] lattice_0.22-9 MASS_7.3-65 backports_1.5.1
## [16] magrittr_2.0.5 plotly_4.12.0 sass_0.4.10
## [19] rmarkdown_2.31 jquerylib_0.1.4 yaml_2.3.12
## [22] httpuv_1.6.17 otel_0.2.0 Seurat_5.5.0
## [25] sctransform_0.4.3 spam_2.11-3 sp_2.2-1
## [28] spatstat.sparse_3.1-0 reticulate_1.46.0 cowplot_1.2.0
## [31] pbapply_1.7-4 DBI_1.3.0 RColorBrewer_1.1-3
## [34] abind_1.4-8 Rtsne_0.17 purrr_1.2.2
## [37] BiocGenerics_0.58.1 rappdirs_0.3.4 IRanges_2.46.0
## [40] S4Vectors_0.50.1 ggrepel_0.9.8 irlba_2.3.7
## [43] listenv_0.10.1 spatstat.utils_3.2-3 goftest_1.2-3
## [46] RSpectra_0.16-2 spatstat.random_3.4-5 fitdistrplus_1.2-6
## [49] parallelly_1.47.0 codetools_0.2-20 tidyselect_1.2.1
## [52] shape_1.4.6.1 farver_2.1.2 matrixStats_1.5.0
## [55] stats4_4.6.0 BiocFileCache_3.2.0 spatstat.explore_3.8-0
## [58] Seqinfo_1.2.0 jsonlite_2.0.0 progressr_0.19.0
## [61] Formula_1.2-5 ggridges_0.5.7 survival_3.8-6
## [64] iterators_1.0.14 foreach_1.5.2 tools_4.6.0
## [67] ica_1.0-3 Rcpp_1.1.1-1.1 glue_1.8.1
## [70] gridExtra_2.3 mgcv_1.9-4 qs2_0.2.1
## [73] xfun_0.57 dplyr_1.2.1 withr_3.0.2
## [76] BiocManager_1.30.27 fastmap_1.2.0 digest_0.6.39
## [79] R6_2.6.1 mime_0.13 scattermore_1.2
## [82] tensor_1.5.1 dichromat_2.0-0.1 spatstat.data_3.1-9
## [85] RSQLite_3.52.0 tidyr_1.3.2 generics_0.1.4
## [88] data.table_1.18.4 httr_1.4.8 htmlwidgets_1.6.4
## [91] uwot_0.2.4 pkgconfig_2.0.3 gtable_0.3.6
## [94] blob_1.3.0 lmtest_0.9-40 S7_0.2.2
## [97] XVector_0.52.0 htmltools_0.5.9 carData_3.0-6
## [100] dotCall64_1.2 bookdown_0.46 SeuratObject_5.4.0
## [103] scales_1.4.0 Biobase_2.72.0 png_0.1-9
## [106] spatstat.univar_3.1-7 knitr_1.51 reshape2_1.4.5
## [109] nlme_3.1-169 curl_7.1.0 cachem_1.1.0
## [112] zoo_1.8-15 stringr_1.6.0 BiocVersion_3.23.1
## [115] KernSmooth_2.23-26 parallel_4.6.0 miniUI_0.1.2
## [118] AnnotationDbi_1.74.0 pillar_1.11.1 grid_4.6.0
## [121] vctrs_0.7.3 RANN_2.6.2 promises_1.5.0
## [124] stringfish_0.19.0 car_3.1-5 dbplyr_2.5.2
## [127] xtable_1.8-8 cluster_2.1.8.2 evaluate_1.0.5
## [130] magick_2.9.1 tinytex_0.59 cli_3.6.6
## [133] compiler_4.6.0 crayon_1.5.3 rlang_1.2.0
## [136] future.apply_1.20.2 ggsignif_0.6.4 labeling_0.4.3
## [139] plyr_1.8.9 stringi_1.8.7 viridisLite_0.4.3
## [142] deldir_2.0-4 Biostrings_2.80.0 lazyeval_0.2.3
## [145] spatstat.geom_3.7-3 glmnet_5.0 Matrix_1.7-5
## [148] ExperimentHub_3.2.0 RcppHNSW_0.6.0 bit64_4.8.0
## [151] future_1.70.0 KEGGREST_1.52.0 shiny_1.13.0
## [154] AnnotationHub_4.2.0 ROCR_1.0-12 igraph_2.3.1
## [157] broom_1.0.13 memoise_2.0.1 RcppParallel_5.1.11-2
## [160] bslib_0.11.0 bit_4.6.0