This vignette analyzes GSE63409, an Illumina 450K methylation dataset from acute myeloid leukemia (AML). The dataset contains 15 AML patients represented by leukemia stem and blast cell samples, and normal hematopoietic stem and progenitor cell controls from healthy bone marrow.
The original study, Hu et al. 2019 (doi:10.21037/atm.2019.11.122), used GSE63409 together with an expression dataset to identify AML-relevant methylation/expression signals, immune and differentiation pathways, and candidate prognostic genes.
try(devtools::load_all(), silent = TRUE)
suppressPackageStartupMessages({
try(library(CMEnt), silent = TRUE)
library(minfi)
library(data.table)
library(ggplot2)
library(dplyr)
library(GenomicRanges)
})
getBenchmarkFile <- function(filename) {
benchmark_file <- ""
folder <- "microarray450k"
if (getwd() == "notebooks") {
benchmark_file <- file.path("cached_results", folder, filename)
} else if ("NAMESPACE" %in% dir()) {
benchmark_file <- file.path("notebooks", "cached_results", folder, filename)
} else {
benchmark_file <- file.path("cached_results", folder, filename)
}
dir.create(dirname(benchmark_file), showWarnings = FALSE, recursive = TRUE)
benchmark_file
}
split_ids <- function(x) {
ids <- unlist(strsplit(stats::na.omit(as.character(x)), ","), use.names = FALSE)
unique(ids[nzchar(ids)])
}
has_text <- function(x) {
!is.na(x) & nzchar(as.character(x))
}
short_label <- function(x, width = 65L) {
ifelse(nchar(x) > width, paste0(substr(x, 1L, width - 3L), "..."), x)
}
r <- getOption("repos")
if (is.null(r) || is.na(r["CRAN"]) || r["CRAN"] %in% c("@CRAN@", "")) {
options(repos = c(CRAN = "https://cloud.r-project.org"))
}
if (!requireNamespace("BiocManager", quietly = TRUE)) {
install.packages("BiocManager")
}
if (!requireNamespace("tidyr", quietly = TRUE)) {
install.packages("tidyr")
}
if (!requireNamespace("scales", quietly = TRUE)) {
install.packages("scales")
}
if (!requireNamespace("IlluminaHumanMethylation450kanno.ilmn12.hg19", quietly = TRUE)) {
BiocManager::install("IlluminaHumanMethylation450kanno.ilmn12.hg19", update = FALSE, ask = FALSE)
}
if (!requireNamespace("TxDb.Hsapiens.UCSC.hg19.knownGene", quietly = TRUE)) {
BiocManager::install("TxDb.Hsapiens.UCSC.hg19.knownGene", update = FALSE, ask = FALSE)
}
if (!requireNamespace("org.Hs.eg.db", quietly = TRUE)) {
BiocManager::install("org.Hs.eg.db", update = FALSE, ask = FALSE)
}
if (!requireNamespace("missMethyl", quietly = TRUE)) {
BiocManager::install("missMethyl", update = FALSE, ask = FALSE)
}
Covariates are: - predictedSex: the sex predicted from methylation data, which can be a strong confounder in methylation analyses. - subject.id.ch1: the patient ID - source_name_ch1: the cell type
covariates <- c("predictedSex", "subject.id.ch1", "source_name_ch1")
sample_group_col <- "subject.status.ch1"
beta <- getBenchmarkFile("GSE63409_beta_values.tsv.gz")
samplesheet <- getBenchmarkFile("GSE63409_samplesheet.tsv")
zenodo_base_url <- "https://zenodo.org/records/20592944/files/"
if (!file.exists(beta)) {
curl::curl_download(
url = paste0(zenodo_base_url, basename(beta), "?download=1"),
destfile = beta
)
}
if (!file.exists(samplesheet)) {
curl::curl_download(
url = paste0(zenodo_base_url, basename(samplesheet), "?download=1"),
destfile = samplesheet
)
}
pheno <- fread(samplesheet)
pheno[[sample_group_col]] <- factor(pheno[[sample_group_col]], levels = c("normal", "AML"))
pheno <- as.data.frame(pheno)
rownames(pheno) <- pheno$V1
array_type <- "450K"
genome <- "hg19"
beta_handler <- CMEnt::getBetaHandler(beta, array = array_type, genome = genome)
beta_mat <- as.matrix(beta_handler$getBeta())
locs <- beta_handler$getBetaLocs()
logit2 <- function(x) log2(x) - log2(1 - x)
mvalues <- logit2(beta_mat)
pheno$casecontrol <- pheno[[sample_group_col]] == "AML"
dmps_file <- getBenchmarkFile("dmps.rds")
if (!file.exists(dmps_file)) {
dmps <- CMEnt::findDMPsArray(
beta_handler,
pheno,
sample_group_col = sample_group_col,
id_col = "V1",
covariates = covariates,
array = array_type,
genome = genome,
njobs = max(1L, min(8L, parallel::detectCores(logical = TRUE) - 1L))
)
# sort DMPs by location
rownames(dmps) <- dmps$site_id
dmps <- dmps[rownames(locs), , drop = FALSE]
dmps <- dmps[!is.na(dmps$pval), ]
dmps$qval <- p.adjust(dmps$pval, method = "BH")
case_idx <- which(pheno$casecontrol)
ctrl_idx <- which(!pheno$casecontrol)
dmps$delta_beta <- rowMeans(beta_mat[rownames(dmps), case_idx, drop = FALSE]) -
rowMeans(beta_mat[rownames(dmps), ctrl_idx, drop = FALSE])
dmps_gr <- makeGRangesFromDataFrame(
data.frame(
chr = locs$chr,
start = locs$start,
end = locs$end,
pval = dmps$pval,
qval = dmps$qval,
stat = dmps$qval,
delta_beta = dmps$delta_beta
),
keep.extra.columns = TRUE
)
names(dmps_gr) <- rownames(dmps)
saveRDS(dmps_gr, dmps_file)
} else {
dmps_gr <- readRDS(dmps_file)
}
dmps <- as.data.frame(dmps_gr)
sig_dmps <- dmps[dmps$qval < 0.05 & abs(dmps$delta_beta) >= 0.05, ]
cat(sprintf("Found %d significant DMPs (FDR < 0.05, |delta beta| >= 0.05)\n", nrow(sig_dmps)))
Found 72556 significant DMPs (FDR < 0.05, |delta beta| >= 0.05)
cment_file <- getBenchmarkFile("dmrs.CMEnt.rds")
if (!file.exists(cment_file)) {
cment_njobs <- max(1L, min(8L, parallel::detectCores(logical = TRUE) - 1L))
options("CMEnt.verbose" = 1)
options("CMEnt.njobs" = cment_njobs)
cat(sprintf("CMEnt parallel jobs: %d\n", cment_njobs))
cat(sprintf("parallel::detectCores(): %d\n", parallel::detectCores(logical = TRUE)))
cat("Starting CMEnt::buildDMRs()...\n")
flush.console()
start_time <- Sys.time()
dmrs_cment <- CMEnt::buildDMRs(
beta = beta_handler,
seeds = sig_dmps,
pheno = pheno,
sample_group_col = sample_group_col,
casecontrol_col = "casecontrol",
covariates = covariates,
max_bridge_seeds_gaps = 1,
max_bridge_extension_gaps = 3,
min_seeds = 2,
min_sites = 3,
ext_site_delta_beta = 0.2,
max_lookup_dist = 1000,
max_pval = 0.05,
entanglement = "weak",
njobs = cment_njobs,
verbose = 1
)
end_time <- Sys.time()
time_cment <- end_time - start_time
saveRDS(list(dmrs = dmrs_cment, time = time_cment), cment_file)
} else {
ret <- readRDS(cment_file)
dmrs_cment <- ret$dmrs
time_cment <- ret$time
}
cat(sprintf("CMEnt: Found %d DMRs in %d seconds\n", length(dmrs_cment), round(as.numeric(time_cment, units = "secs"))))
CMEnt: Found 8654 DMRs in 1049 seconds
if (!all(c("in_promoter_of", "in_gene_body_of", "delta_beta_promoter", "delta_beta_gene_body") %in% colnames(mcols(dmrs_cment))) &&
requireNamespace("TxDb.Hsapiens.UCSC.hg19.knownGene", quietly = TRUE) &&
requireNamespace("org.Hs.eg.db", quietly = TRUE)) {
dmrs_cment <- CMEnt::annotateDMRsWithGenes(dmrs_cment, genome = genome)
}
for (gene_col in c("in_promoter_of", "in_gene_body_of")) {
if (!gene_col %in% colnames(mcols(dmrs_cment))) {
mcols(dmrs_cment)[[gene_col]] <- NA_character_
}
}
for (delta_col in c("delta_beta_promoter", "delta_beta_gene_body")) {
if (!delta_col %in% colnames(mcols(dmrs_cment))) {
mcols(dmrs_cment)[[delta_col]] <- NA_real_
}
}
dmr_delta_col <- if ("sites_delta_beta" %in% colnames(mcols(dmrs_cment))) {
"sites_delta_beta"
} else {
"delta_beta"
}
dmr_delta <- as.numeric(mcols(dmrs_cment)[[dmr_delta_col]])
dmr_direction <- ifelse(dmr_delta > 0, "Hypermethylated in AML", "Hypomethylated in AML")
dmr_summary <- data.frame(
DMRs = length(dmrs_cment),
Median_width_bp = median(width(dmrs_cment)),
Mean_width_bp = round(mean(width(dmrs_cment)), 1),
Total_coverage_bp = sum(width(dmrs_cment)),
Median_delta_beta = round(median(dmr_delta, na.rm = TRUE), 4),
Mean_abs_delta_beta = round(mean(abs(dmr_delta), na.rm = TRUE), 4),
Hypermethylated_DMRs = sum(dmr_delta > 0, na.rm = TRUE),
Hypomethylated_DMRs = sum(dmr_delta < 0, na.rm = TRUE)
)
knitr::kable(dmr_summary, caption = "CMEnt DMR summary for AML versus normal samples")
| DMRs | Median_width_bp | Mean_width_bp | Total_coverage_bp | Median_delta_beta | Mean_abs_delta_beta | Hypermethylated_DMRs | Hypomethylated_DMRs |
|---|---|---|---|---|---|---|---|
| 8654 | 1315 | 1740.2 | 15059673 | 0.0082 | 0.1087 | 5034 | 3620 |
dmrs_cment_only_promoter_or_gene_body <- dmrs_cment[!(is.finite(mcols(dmrs_cment)$delta_beta_promoter) & is.finite(mcols(dmrs_cment)$delta_beta_gene_body))]
dmr_effect_df <- bind_rows(
data.frame(
Region = "Promoter-overlapping DMRs",
Width = width(dmrs_cment_only_promoter_or_gene_body),
Delta_beta = as.numeric(mcols(dmrs_cment_only_promoter_or_gene_body)$delta_beta_promoter)
),
data.frame(
Region = "Gene-body-overlapping DMRs",
Width = width(dmrs_cment_only_promoter_or_gene_body),
Delta_beta = as.numeric(mcols(dmrs_cment_only_promoter_or_gene_body)$delta_beta_gene_body)
)
) |>
filter(is.finite(Delta_beta)) |>
mutate(Direction = factor(
ifelse(Delta_beta > 0, "Hypermethylated in AML", "Hypomethylated in AML"),
levels = c("Hypermethylated in AML", "Hypomethylated in AML")
))
library(dplyr)
library(ggplot2)
library(scales)
ignore_abs_delta <- !is.finite(dmr_effect_df$Delta_beta) | abs(dmr_effect_df$Delta_beta) < 0.05
dmr_effect_df <- dmr_effect_df[!ignore_abs_delta,]
# Summary per Region and Direction
dmr_summary <- dmr_effect_df %>%
group_by(Region, Direction) %>%
summarise(
median_delta_beta = median(Delta_beta, na.rm = TRUE),
n_dmrs = n(),
.groups = "drop"
)
# Define two y-levels for the two summary bars
y_max <- max(dmr_effect_df$Width, na.rm = TRUE)
dmr_summary <- dmr_summary %>%
mutate(
bar_y = case_when(
Direction == "Hypermethylated in AML" ~ y_max * 2.0,
Direction == "Hypomethylated in AML" ~ y_max * 3.2
),
label_y = bar_y * 1.12
)
# Expand y-range so the bars and labels fit
y_upper <- max(dmr_summary$label_y) * 1.15
ggplot(dmr_effect_df, aes(x = Delta_beta, y = Width, color = Direction)) +
geom_hline(
yintercept = median(dmr_effect_df$Width, na.rm = TRUE),
linewidth = 0.2,
color = "grey70"
) +
geom_vline(xintercept = 0, linewidth = 0.2, color = "grey70") +
geom_point(alpha = 0.55, size = 1.2) +
# Separate horizontal bars for hypo and hyper
geom_segment(
data = dmr_summary,
aes(
x = 0,
xend = median_delta_beta,
y = bar_y,
yend = bar_y,
color = Direction
),
inherit.aes = FALSE,
linewidth = 5,
lineend = "butt"
) +
# Labels for each bar
geom_text(
data = dmr_summary,
aes(
x = median_delta_beta,
y = label_y,
label = paste0(
"median Δβ = ", round(median_delta_beta, 3),
"\nDMRs = ", n_dmrs
)
),
inherit.aes = FALSE,
color = "black",
size = 3,
hjust = ifelse(dmr_summary$median_delta_beta >= 0, -0.05, 1.05)
) +
facet_wrap(~Region, nrow = 1) +
scale_y_log10(
limits = c(min(dmr_effect_df$Width[dmr_effect_df$Width > 0], na.rm = TRUE), y_upper),
labels = comma
) +
scale_color_manual(
values = c(
"Hypermethylated in AML" = "#B8405E",
"Hypomethylated in AML" = "#247BA0"
)
) +
coord_cartesian(clip = "off") +
theme_minimal() +
labs(
title = "CMEnt DMR Effect Size and Width by Gene Context",
x = "Context-specific delta beta (AML - normal)",
y = "DMR width (bp, log scale)",
color = ""
)
gene_context_df <- data.frame(
Context = c("Promoter", "Gene body", "Promoter and gene body", "No annotated gene overlap"),
DMRs = c(
sum(has_text(mcols(dmrs_cment)$in_promoter_of)),
sum(has_text(mcols(dmrs_cment)$in_gene_body_of)),
sum(has_text(mcols(dmrs_cment)$in_promoter_of) & has_text(mcols(dmrs_cment)$in_gene_body_of)),
sum(!has_text(mcols(dmrs_cment)$in_promoter_of) & !has_text(mcols(dmrs_cment)$in_gene_body_of))
)
) |>
mutate(Percentage = round(100 * DMRs / length(dmrs_cment), 1))
knitr::kable(gene_context_df, caption = "Gene context of CMEnt DMRs")
| Context | DMRs | Percentage |
|---|---|---|
| Promoter | 5701 | 65.9 |
| Gene body | 7379 | 85.3 |
| Promoter and gene body | 5560 | 64.2 |
| No annotated gene overlap | 1134 | 13.1 |
ggplot(gene_context_df, aes(x = reorder(Context, DMRs), y = DMRs, fill = Context)) +
geom_col(width = 0.7) +
coord_flip() +
scale_y_continuous(labels = scales::comma) +
theme_minimal() +
theme(legend.position = "none") +
labs(title = "CMEnt DMR Gene Context", x = "", y = "DMRs")
if (requireNamespace("IlluminaHumanMethylation450kanno.ilmn12.hg19", quietly = TRUE)) {
library(IlluminaHumanMethylation450kanno.ilmn12.hg19)
anno <- as.data.frame(minfi::getAnnotation(IlluminaHumanMethylation450kanno.ilmn12.hg19))
anno$probe_id <- rownames(anno)
dmr_site_ids <- split_ids(mcols(dmrs_cment)$sites)
dmr_site_context <- anno[intersect(dmr_site_ids, rownames(anno)), c("probe_id", "Relation_to_Island")]
dmp_site_context <- anno[intersect(rownames(sig_dmps), rownames(anno)), c("probe_id", "Relation_to_Island")]
site_context_df <- bind_rows(
dmp_site_context |> mutate(Source = "Significant DMPs"),
dmr_site_context |> mutate(Source = "Sites inside CMEnt DMRs")
) |>
count(Source, Relation_to_Island, name = "Sites") |>
group_by(Source) |>
mutate(Percentage = round(100 * Sites / sum(Sites), 1)) |>
ungroup()
knitr::kable(site_context_df, caption = "CpG island context of significant DMPs and sites inside CMEnt DMRs")
}
| Source | Relation_to_Island | Sites | Percentage |
|---|---|---|---|
| Significant DMPs | Island | 15527 | 21.4 |
| Significant DMPs | N_Shelf | 3821 | 5.3 |
| Significant DMPs | N_Shore | 12188 | 16.8 |
| Significant DMPs | OpenSea | 28474 | 39.2 |
| Significant DMPs | S_Shelf | 3289 | 4.5 |
| Significant DMPs | S_Shore | 9257 | 12.8 |
| Sites inside CMEnt DMRs | Island | 34457 | 44.3 |
| Sites inside CMEnt DMRs | N_Shelf | 2049 | 2.6 |
| Sites inside CMEnt DMRs | N_Shore | 15149 | 19.5 |
| Sites inside CMEnt DMRs | OpenSea | 13572 | 17.5 |
| Sites inside CMEnt DMRs | S_Shelf | 1403 | 1.8 |
| Sites inside CMEnt DMRs | S_Shore | 11136 | 14.3 |
if (exists("site_context_df")) {
context_levels <- site_context_df |>
group_by(Relation_to_Island) |>
summarise(Max_sites = max(Sites), .groups = "drop") |>
arrange(Max_sites) |>
pull(Relation_to_Island)
plot_context_df <- site_context_df |>
mutate(
Relation_to_Island = factor(Relation_to_Island, levels = context_levels),
Source = factor(Source, levels = c("Significant DMPs", "Sites inside CMEnt DMRs"))
)
diff_df <- plot_context_df |>
dplyr::select(Source, Relation_to_Island, Sites) |>
tidyr::pivot_wider(names_from = Source, values_from = Sites, values_fill = 0) |>
dplyr::mutate(
Difference = `Sites inside CMEnt DMRs` - `Significant DMPs`,
Label = paste0("Delta=", scales::comma(Difference)),
Label_x = pmax(`Significant DMPs`, `Sites inside CMEnt DMRs`)
)
ggplot(plot_context_df, aes(x = Sites, y = Relation_to_Island, fill = Source)) +
geom_col(data = dplyr::filter(plot_context_df, Source == "Significant DMPs"), width = 0.78, alpha = 0.45) +
geom_col(data = dplyr::filter(plot_context_df, Source == "Sites inside CMEnt DMRs"), width = 0.48, alpha = 0.9) +
geom_text(data = diff_df, aes(x = Label_x, y = Relation_to_Island, label = Label), inherit.aes = FALSE, hjust = -0.05, size = 3) +
scale_x_continuous(labels = scales::comma, expand = expansion(mult = c(0, 0.2))) +
scale_fill_manual(values = c("Significant DMPs" = "grey65", "Sites inside CMEnt DMRs" = "#0072B2")) +
theme_minimal() +
labs(title = "CpG Island Context", x = "Sites", y = "", fill = "")
}
The table below is a targeted DMR scan of AML genetics, signaling, and hematopoietic/myeloid marker genes.
gene_pattern <- function(gene) {
paste0("(^|,)", gene, "($|,)")
}
dmr_gene_summary <- function(gene) {
promoter_hits <- grepl(gene_pattern(gene), as.character(mcols(dmrs_cment)$in_promoter_of))
body_hits <- grepl(gene_pattern(gene), as.character(mcols(dmrs_cment)$in_gene_body_of))
dmr_hits <- promoter_hits | body_hits
data.frame(
Gene = gene,
CMEnt_DMRs = sum(dmr_hits),
Promoter_DMRs = sum(promoter_hits),
Gene_body_DMRs = sum(body_hits),
Mean_DMR_delta_beta = round(mean(dmr_delta[dmr_hits], na.rm = TRUE), 4)
)
}
aml_prior_genes <- data.frame(
Gene = c(
"NPM1", "FLT3", "KIT", "RUNX1", "TP53", "TET2", "DNMT3A", "CXCR4", "NAT10",
"JAK2", "STAT3", "STAT5A", "STAT5B", "HOXA9", "HOXA10",
"CD34", "ITGAM", "SPI1", "CEBPA", "GATA2"
),
Theme = c(
rep("AML genetics/prognosis", 9),
rep("JAK-STAT/HOXA signaling", 6),
rep("Hematopoietic and myeloid differentiation", 5)
)
)
prior_dmr_summary <- bind_rows(lapply(aml_prior_genes$Gene, dmr_gene_summary))
prior_gene_table <- aml_prior_genes |>
left_join(prior_dmr_summary, by = "Gene") |>
mutate(
CMEnt_DMRs = tidyr::replace_na(CMEnt_DMRs, 0L),
Methylation_signal = CMEnt_DMRs > 0
) |>
arrange(desc(Methylation_signal), desc(CMEnt_DMRs), Gene)
knitr::kable(prior_gene_table, digits = 4, caption = "Targeted AML gene scan using CMEnt DMRs")
| Gene | Theme | CMEnt_DMRs | Promoter_DMRs | Gene_body_DMRs | Mean_DMR_delta_beta | Methylation_signal |
|---|---|---|---|---|---|---|
| HOXA9 | JAK-STAT/HOXA signaling | 2 | 1 | 2 | -0.0007 | TRUE |
| CD34 | Hematopoietic and myeloid differentiation | 1 | 1 | 1 | 0.0699 | TRUE |
| GATA2 | Hematopoietic and myeloid differentiation | 1 | 1 | 1 | 0.0149 | TRUE |
| HOXA10 | JAK-STAT/HOXA signaling | 1 | 1 | 1 | 0.0706 | TRUE |
| RUNX1 | AML genetics/prognosis | 1 | 1 | 1 | -0.2875 | TRUE |
| STAT3 | JAK-STAT/HOXA signaling | 1 | 0 | 1 | -0.4134 | TRUE |
| CEBPA | Hematopoietic and myeloid differentiation | 0 | 0 | 0 | NaN | FALSE |
| CXCR4 | AML genetics/prognosis | 0 | 0 | 0 | NaN | FALSE |
| DNMT3A | AML genetics/prognosis | 0 | 0 | 0 | NaN | FALSE |
| FLT3 | AML genetics/prognosis | 0 | 0 | 0 | NaN | FALSE |
| ITGAM | Hematopoietic and myeloid differentiation | 0 | 0 | 0 | NaN | FALSE |
| JAK2 | JAK-STAT/HOXA signaling | 0 | 0 | 0 | NaN | FALSE |
| KIT | AML genetics/prognosis | 0 | 0 | 0 | NaN | FALSE |
| NAT10 | AML genetics/prognosis | 0 | 0 | 0 | NaN | FALSE |
| NPM1 | AML genetics/prognosis | 0 | 0 | 0 | NaN | FALSE |
| SPI1 | Hematopoietic and myeloid differentiation | 0 | 0 | 0 | NaN | FALSE |
| STAT5A | JAK-STAT/HOXA signaling | 0 | 0 | 0 | NaN | FALSE |
| STAT5B | JAK-STAT/HOXA signaling | 0 | 0 | 0 | NaN | FALSE |
| TET2 | AML genetics/prognosis | 0 | 0 | 0 | NaN | FALSE |
| TP53 | AML genetics/prognosis | 0 | 0 | 0 | NaN | FALSE |
prior_plot_df <- prior_gene_table |>
filter(Methylation_signal) |>
mutate(Gene = reorder(Gene, CMEnt_DMRs))
if (nrow(prior_plot_df) > 0) {
ggplot(prior_plot_df, aes(x = Gene, y = CMEnt_DMRs, fill = Theme)) +
geom_col(width = 0.7) +
coord_flip() +
theme_minimal() +
labs(title = "AML Genes Overlapping CMEnt DMRs", x = "", y = "CMEnt DMRs", fill = "")
}
missMethyl performs methylation-array-aware enrichment for CMEnt DMRs while correcting for
probe-number bias across genes.
aml_term_pattern <- paste(
c(
"acute myeloid", "leukemia", "leukaemia", "myeloid", "hematopoiet", "haematopoiet",
"stem cell", "differentiation", "immune", "leukocyte", "lymphocyte", "granulocyte",
"monocyte", "macrophage", "cytokine", "chemokine", "phagosome", "JAK", "STAT",
"HOX", "FLT3", "NPM1", "DNA methylation", "apoptosis", "cell cycle",
"transcriptional misregulation"
),
collapse = "|"
)
normalize_missmethyl_result <- function(x, collection) {
if (is.null(x) || nrow(x) == 0L) {
return(NULL)
}
x <- as.data.frame(x)
term_col <- intersect(c("Term", "TERM", "Description", "Pathway"), colnames(x))[1]
fdr_col <- intersect(c("FDR", "adj.P.Val", "P.DE", "P.Value"), colnames(x))[1]
p_col <- intersect(c("P.DE", "P.Value", "P.DE.weighted"), colnames(x))[1]
de_col <- intersect(c("DE", "N_DE", "Count"), colnames(x))[1]
n_col <- intersect(c("N", "Total", "Size"), colnames(x))[1]
ont_col <- intersect(c("Ont", "Ontology", "Category"), colnames(x))[1]
if (is.na(term_col) || is.na(fdr_col)) {
return(NULL)
}
data.frame(
Collection = collection,
Term = as.character(x[[term_col]]),
Ontology = if (!is.na(ont_col)) as.character(x[[ont_col]]) else collection,
N = if (!is.na(n_col)) suppressWarnings(as.numeric(x[[n_col]])) else NA_real_,
DE = if (!is.na(de_col)) suppressWarnings(as.numeric(x[[de_col]])) else NA_real_,
PValue = if (!is.na(p_col)) suppressWarnings(as.numeric(x[[p_col]])) else NA_real_,
FDR = suppressWarnings(as.numeric(x[[fdr_col]])),
stringsAsFactors = FALSE
)
}
missmethyl_long <- NULL
if (requireNamespace("missMethyl", quietly = TRUE) &&
requireNamespace("IlluminaHumanMethylation450kanno.ilmn12.hg19", quietly = TRUE)) {
library(IlluminaHumanMethylation450kanno.ilmn12.hg19)
cached <- getBenchmarkFile("missmethyl_cment_enrichment_results.rds")
if (file.exists(cached)) {
missmethyl_long <- readRDS(cached)
} else {
missmethyl_long <- base::do.call(rbind, Filter(Negate(is.null), lapply(c("GO", "KEGG"), function(collection) {
ret <- tryCatch(
missMethyl::goregion(
regions = dmrs_cment,
all.cpg = rownames(locs),
collection = collection,
array.type = "450K",
plot.bias = FALSE,
prior.prob = TRUE
),
error = function(e) {
warning(sprintf("missMethyl %s enrichment failed for CMEnt DMRs: %s", collection, e$message))
NULL
}
)
normalize_missmethyl_result(ret, collection)
})))
saveRDS(missmethyl_long, cached)
}
} else {
cat("missMethyl or the 450K annotation package is required for GO/KEGG enrichment.\n")
}
if (!is.null(missmethyl_long) && nrow(missmethyl_long) > 0L) {
missmethyl_long <- missmethyl_long[is.finite(missmethyl_long$FDR), , drop = FALSE]
missmethyl_long$NegLog10FDR <- -log10(pmax(missmethyl_long$FDR, .Machine$double.xmin))
missmethyl_long$AML_Context <- ifelse(grepl(aml_term_pattern, missmethyl_long$Term, ignore.case = TRUE), "AML-context term", "Other top term")
missmethyl_top <- missmethyl_long |>
group_by(Collection) |>
arrange(FDR, .by_group = TRUE) |>
slice_head(n = 10) |>
ungroup()
missmethyl_top$Term_Label <- short_label(missmethyl_top$Term, 70)
missmethyl_top$Term_Collection <- factor(
paste(missmethyl_top$Term_Label, missmethyl_top$Collection, sep = "___"),
levels = rev(unique(paste(missmethyl_top$Term_Label, missmethyl_top$Collection, sep = "___")))
)
knitr::kable(
missmethyl_top |>
dplyr::select(Collection, Ontology, Term, N, DE, PValue, FDR, AML_Context) |>
arrange(Collection, FDR),
digits = 3,
row.names = FALSE,
caption = "Top missMethyl GO/KEGG enrichments from CMEnt DMRs"
)
}
| Collection | Ontology | Term | N | DE | PValue | FDR | AML_Context |
|---|---|---|---|---|---|---|---|
| GO | GO | cell periphery | 5528 | 2122 | 0 | 0.000 | Other top term |
| GO | GO | system development | 3248 | 1426 | 0 | 0.000 | Other top term |
| GO | GO | multicellular organismal process | 6251 | 2353 | 0 | 0.000 | Other top term |
| GO | GO | anatomical structure development | 4906 | 1970 | 0 | 0.000 | Other top term |
| GO | GO | multicellular organism development | 3760 | 1586 | 0 | 0.000 | Other top term |
| GO | GO | developmental process | 5445 | 2140 | 0 | 0.000 | Other top term |
| GO | GO | nervous system development | 2074 | 978 | 0 | 0.000 | Other top term |
| GO | GO | plasma membrane | 5086 | 1931 | 0 | 0.000 | Other top term |
| GO | GO | cell-cell signaling | 1146 | 546 | 0 | 0.000 | Other top term |
| GO | GO | gated channel activity | 298 | 183 | 0 | 0.000 | Other top term |
| KEGG | KEGG | Neuroactive ligand-receptor interaction | 341 | 180 | 0 | 0.000 | Other top term |
| KEGG | KEGG | Neuroactive ligand signaling | 192 | 120 | 0 | 0.000 | Other top term |
| KEGG | KEGG | Cadherin signaling | 392 | 185 | 0 | 0.000 | Other top term |
| KEGG | KEGG | Nicotine addiction | 36 | 30 | 0 | 0.000 | Other top term |
| KEGG | KEGG | Calcium signaling pathway | 238 | 129 | 0 | 0.000 | Other top term |
| KEGG | KEGG | Cell adhesion molecule (CAM) interaction | 144 | 77 | 0 | 0.000 | Other top term |
| KEGG | KEGG | Type I diabetes mellitus | 42 | 27 | 0 | 0.004 | Other top term |
| KEGG | KEGG | Hormone signaling | 209 | 93 | 0 | 0.007 | Other top term |
| KEGG | KEGG | Signaling pathways regulating pluripotency of stem cells | 138 | 74 | 0 | 0.007 | AML-context term |
| KEGG | KEGG | Morphine addiction | 88 | 52 | 0 | 0.007 | Other top term |
if (!is.null(missmethyl_long) && nrow(missmethyl_long) > 0L) {
ggplot(missmethyl_top, aes(x = NegLog10FDR, y = Term_Collection, size = DE, color = AML_Context)) +
geom_point(alpha = 0.9) +
facet_wrap(~Collection, scales = "free_y") +
scale_y_discrete(labels = function(x) sub("___.*$", "", x)) +
scale_color_manual(values = c("AML-context term" = "#B8405E", "Other top term" = "grey50")) +
theme_minimal() +
theme(axis.text.y = element_text(size = 7)) +
labs(title = "missMethyl Enrichment", x = expression(-log[10]("FDR")), y = "", color = "", size = "DM genes")
} else {
cat("missMethyl returned no enrichment results.\n")
}
focused_terms <- if (!is.null(missmethyl_long) && nrow(missmethyl_long) > 0L) {
missmethyl_long |>
filter(grepl(aml_term_pattern, Term, ignore.case = TRUE)) |>
group_by(Collection) |>
arrange(FDR, .by_group = TRUE) |>
slice_head(n = 8) |>
ungroup()
} else {
data.frame()
}
if (nrow(focused_terms) > 0L) {
focused_terms$Term_Label <- short_label(focused_terms$Term, 62)
focused_terms$Term_Collection <- factor(
paste(focused_terms$Term_Label, focused_terms$Collection, sep = "___"),
levels = rev(unique(paste(focused_terms$Term_Label, focused_terms$Collection, sep = "___")))
)
knitr::kable(
focused_terms |>
dplyr::select(Collection, Ontology, Term, N, DE, PValue, FDR) |>
arrange(Collection, FDR),
digits = 3,
row.names = FALSE,
caption = "Top AML-relevant GO/KEGG terms"
)
}
| Collection | Ontology | Term | N | DE | PValue | FDR |
|---|---|---|---|---|---|---|
| GO | GO | cell differentiation | 3702 | 1479 | 0.000 | 0.000 |
| GO | GO | neuron differentiation | 1112 | 534 | 0.000 | 0.000 |
| GO | GO | positive regulation of cell differentiation | 738 | 334 | 0.000 | 0.000 |
| GO | GO | central nervous system neuron differentiation | 115 | 76 | 0.000 | 0.000 |
| GO | GO | regulation of cell differentiation | 1331 | 545 | 0.000 | 0.000 |
| GO | GO | muscle cell differentiation | 350 | 166 | 0.000 | 0.000 |
| GO | GO | striated muscle cell differentiation | 263 | 123 | 0.000 | 0.002 |
| GO | GO | regulation of neuron differentiation | 114 | 65 | 0.000 | 0.004 |
| KEGG | KEGG | Signaling pathways regulating pluripotency of stem cells | 138 | 74 | 0.000 | 0.007 |
| KEGG | KEGG | Autoimmune thyroid disease | 39 | 21 | 0.003 | 0.063 |
| KEGG | KEGG | Hematopoietic cell lineage | 90 | 37 | 0.013 | 0.138 |
| KEGG | KEGG | Cytokine-cytokine receptor interaction | 258 | 84 | 0.020 | 0.186 |
| KEGG | KEGG | Intestinal immune network for IgA production | 45 | 20 | 0.032 | 0.282 |
| KEGG | KEGG | Viral protein interaction with cytokine and cytokine receptor | 89 | 26 | 0.161 | 0.716 |
| KEGG | KEGG | Chemokine signaling pathway | 181 | 54 | 0.834 | 1.000 |
| KEGG | KEGG | Cell cycle | 153 | 22 | 1.000 | 1.000 |
if (nrow(focused_terms) > 0L) {
ggplot(focused_terms, aes(x = -log10(pmax(FDR, .Machine$double.xmin)), y = Term_Collection, fill = Collection)) +
geom_col(width = 0.7) +
facet_wrap(~Collection, scales = "free_y") +
scale_y_discrete(labels = function(x) sub("___.*$", "", x)) +
theme_minimal() +
theme(axis.text.y = element_text(size = 8), legend.position = "none") +
labs(title = "AML-Relevant Enrichment Terms", x = expression(-log[10]("FDR")), y = "")
} else {
cat("No missMethyl terms matched the AML-focused keyword set.\n")
}
dmr_table <- as.data.frame(dmrs_cment)
dmr_table$DMR <- paste0(dmr_table$seqnames, ":", dmr_table$start, "-", dmr_table$end)
dmr_table$delta_beta_for_ranking <- dmr_delta
dmr_table$abs_delta_beta <- abs(dmr_delta)
dmr_table$svm_score_for_ranking <- if ("score" %in% colnames(dmr_table)) dmr_table$score else 0
if (!"qval" %in% colnames(dmr_table)) {
dmr_table$qval <- NA_real_
}
if (!"pval" %in% colnames(dmr_table)) {
dmr_table$pval <- NA_real_
}
if (!"score" %in% colnames(dmr_table)) {
dmr_table$score <- NA_real_
}
top_dmrs <- dmr_table |>
filter(has_text(in_promoter_of) | has_text(in_gene_body_of)) |>
arrange(desc(svm_score_for_ranking), qval, desc(abs_delta_beta)) |>
dplyr::select(
DMR,
width,
score,
qval,
pval,
delta_beta_for_ranking,
any_of(c("delta_beta_promoter", "delta_beta_gene_body", "seeds_num", "sites_num", "in_promoter_of", "in_gene_body_of"))
) |>
head(20)
knitr::kable(top_dmrs, digits = 4, caption = "Top 20 promoter or gene-body overlapping CMEnt DMRs ranked by score")
| DMR | width | score | qval | pval | delta_beta_for_ranking | delta_beta_promoter | delta_beta_gene_body | seeds_num | sites_num | in_promoter_of | in_gene_body_of | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| chr1:cg14278300-cg09554443 | chr1:167486978-167487762 | 785 | 0.6566 | 0e+00 | 0e+00 | -0.0627 | -0.3938 | -0.0627 | 2 | 5 | CD247 | CD247 |
| chr8:cg25247520-cg00780520 | chr8:128808017-128808554 | 538 | 0.6352 | 0e+00 | 0e+00 | -0.3510 | -0.3603 | -0.3395 | 3 | 3 | PVT1 | PVT1 |
| chr21:cg05126444-cg16704958 | chr21:38629859-38630728 | 870 | 0.6281 | 0e+00 | 0e+00 | -0.1452 | NA | -0.1452 | 2 | 5 | NA | VPS26C |
| chr17:cg09489844-cg10168457 | chr17:79880647-79882876 | 2230 | 0.6262 | 0e+00 | 0e+00 | -0.0552 | -0.0020 | -0.0020 | 3 | 10 | MAFG-AS1,MAFG,SIRT7,MILIP | MAFG-AS1,MAFG,MILIP |
| chr10:cg10770832-cg09622269 | chr10:76803270-76803925 | 656 | 0.6242 | 0e+00 | 0e+00 | 0.2904 | NA | 0.2755 | 5 | 5 | NA | DUSP29 |
| chr19:cg24291974-cg19417168 | chr19:4531638-4531961 | 324 | 0.6166 | 0e+00 | 0e+00 | -0.4472 | NA | -0.3740 | 4 | 4 | NA | PLIN5 |
| chr11:cg26512142-cg05898618 | chr11:2554198-2555576 | 1379 | 0.6147 | 0e+00 | 0e+00 | -0.0686 | NA | -0.0520 | 4 | 11 | NA | KCNQ1 |
| chr16:cg05673293-cg07605834 | chr16:71475279-71475926 | 648 | 0.6109 | 0e+00 | 0e+00 | 0.4046 | 0.0978 | 0.4250 | 4 | 5 | TLE7 | TLE7 |
| chr10:cg19007269-cg13564061 | chr10:105420501-105421480 | 980 | 0.6092 | 0e+00 | 0e+00 | -0.2460 | -0.3165 | -0.2708 | 4 | 6 | SH3PXD2A | SH3PXD2A |
| chr11:cg18431910-cg13228701 | chr11:78614239-78614522 | 284 | 0.6091 | 1e-04 | 1e-04 | 0.2831 | NA | 0.2831 | 2 | 3 | NA | TENM4 |
| chr7:cg01572810-cg16810272 | chr7:150901654-150902685 | 1032 | 0.6061 | 0e+00 | 0e+00 | 0.3312 | -0.0022 | 0.3526 | 2 | 3 | DRC11L | DRC11L |
| chr6:cg11805138-cg23457357 | chr6:31148332-31148748 | 417 | 0.6030 | 0e+00 | 0e+00 | -0.0579 | -0.0563 | -0.0563 | 11 | 15 | POU5F1 | PSORS1C3,POU5F1 |
| chr17:cg11252953-cg21465176 | chr17:80358829-80358876 | 48 | 0.5986 | 0e+00 | 0e+00 | -0.0269 | NA | -0.0269 | 2 | 3 | NA | OGFOD3 |
| chr2:cg03322446-cg24601559 | chr2:43327014-43328536 | 1523 | 0.5967 | 0e+00 | 0e+00 | 0.3097 | NA | 0.3041 | 6 | 7 | NA | LINC02580,LINC01819 |
| chr3:cg21463380-cg21526749 | chr3:187389127-187389513 | 387 | 0.5967 | 0e+00 | 0e+00 | -0.0854 | -0.0854 | NA | 2 | 3 | SST | NA |
| chr11:cg20244273-cg01607369 | chr11:7597349-7598673 | 1325 | 0.5955 | 0e+00 | 0e+00 | -0.2169 | -0.3501 | -0.1600 | 2 | 5 | PPFIBP2 | PPFIBP2 |
| chr17:cg26118142-cg16810621 | chr17:3289363-3290164 | 802 | 0.5938 | 0e+00 | 0e+00 | 0.1574 | 0.0763 | 0.0763 | 3 | 6 | OR3A2,OR1R1 | OR3A2,OR1R1 |
| chr11:cg10321236-cg03908908 | chr11:76849101-76849564 | 464 | 0.5938 | 0e+00 | 0e+00 | 0.2971 | 0.3106 | 0.3313 | 4 | 4 | MYO7A | MYO7A |
| chr15:cg21819984-cg08428878 | chr15:101084507-101085341 | 835 | 0.5930 | 0e+00 | 0e+00 | 0.2879 | 0.3293 | 0.3515 | 7 | 8 | CERS3 | CERS3 |
| chr1:cg16104450-cg06882058 | chr1:243645911-243646787 | 877 | 0.5923 | 0e+00 | 0e+00 | -0.1044 | NA | -0.1044 | 2 | 7 | NA | SDCCAG8 |
CMEnt::plotDMRs(
dmrs_cment,
top_n = 1,
score_by = "score",
beta = beta_handler,
pheno = pheno,
sample_group_col = sample_group_col,
genome = "hg19",
array = array_type
)
CMEnt::plotDMRsManhattan(
dmrs_cment,
genome = "hg19")
CMEnt::plotDMRsCircos(
dmrs_cment,
genome = "hg19",
array = array_type
)
This CMEnt re-analysis of GSE63409 extends the original Hu et al. study from a gene-level methylation and expression biomarker analysis into a region-level interpretation of AML-associated methylation architecture. Whereas the original publication integrated methylation and expression data to nominate AML-relevant pathways and three prognostic genes, ATP11A, ITGAM, and ZNRF2, this notebook shows that the same methylation dataset contains a broad and spatially coherent regional signal: 72,556 significant DMPs were assembled into 8,654 CMEnt DMRs, covering about 15.1 Mb of the genome, with a slight excess of hypermethylated regions in AML.
A main new observation is that the regional signal is not randomly distributed across gene annotation space. Most CMEnt DMRs overlap annotated genes, especially gene bodies, and many overlap both promoter and gene-body annotations. This suggests that AML-associated methylation changes in this dataset are not limited to isolated promoter CpGs, but frequently form extended regulatory blocks spanning transcriptional units. The effect-size plot further indicates that both promoter-overlapping and gene-body-overlapping DMRs contain clear hypermethylated and hypomethylated subclasses, with gene-body DMRs contributing the larger number of region-level events.
Although significant DMPs are most frequent in OpenSea regions, CpGs retained inside CMEnt DMRs are strongly enriched in CpG islands and shores. This indicates that CMEnt preferentially captures locally coherent methylation changes in CpG-dense regulatory neighborhoods, rather than simply preserving the genome-wide distribution of significant single CpGs. In practical terms, the analysis reframes part of the AML methylation signal as coordinated regional dysregulation around CpG island-associated loci.
The targeted AML gene scan also supports biological relevance while adding positional detail. CMEnt DMRs overlap several AML-associated regulatory and differentiation genes, including HOXA9, HOXA10, RUNX1, STAT3, CD34, and GATA2. This partly recapitulates the original study’s emphasis on hematopoietic differentiation and AML-relevant signaling, but adds information about whether these signals occur as promoter, gene-body, or mixed regional methylation events. Notably, RUNX1 and STAT3 show strong hypomethylated DMR signals, while HOXA10 and CD34 show hypermethylated regional signals, suggesting that AML-associated methylation changes are directionally heterogeneous across disease-relevant loci.
The enrichment results further reinforce the biological interpretation. The strongest GO terms are broad developmental, cell-periphery, cell-signaling, and differentiation categories, while AML-context terms include cell differentiation, regulation of differentiation, stem-cell pluripotency signaling, hematopoietic cell lineage, and cytokine-related pathways. Compared with the original study’s pathway-level analysis, CMEnt adds the observation that these biological themes are supported by coherent DMR structures rather than only by individually significant CpGs or methylation-expression gene intersections.
Finally, the candidate-region and visualization figures provide concrete follow-up loci. The top-scoring DMR overlaps CD247 on chromosome 1, shows clear group separation with cross-validation accuracy of 0.85, and is hypomethylated in AML. Other high-ranking regions include PVT1, RUNX1-associated regulatory candidates through the AML scan, POU5F1, SH3PXD2A, TLE7, KCNQ1, PLIN5, and MAFG/SIRT7-associated loci. The Manhattan and circos plots show that high-scoring DMRs are distributed across many chromosomes, with 115 identified DMR blocks and recurrent motif-interaction patterns involving factors such as KLF-family motifs and AHR::ARNT-like motifs.
Overall, this analysis supports the original conclusion that AML is associated with dysregulated methylation in genes and pathways linked to hematopoietic differentiation, immune signaling, and development. Its main added value is that it converts the single-CpG signal into interpretable regional methylation structures, revealing CpG island-enriched DMR organization, promoter and gene-body-specific effect patterns, and candidate loci that can be prioritized for biological validation.
sessionInfo()
R version 4.6.0 (2026-04-24) Platform: x86_64-pc-linux-gnu Running under: Ubuntu 24.04.4 LTS
Matrix products: default BLAS: /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.12.0 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_US.UTF-8 LC_COLLATE=en_US.UTF-8
[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: Europe/Brussels tzcode source: system (glibc)
attached base packages:
[1] parallel stats4 stats graphics grDevices datasets utils
[8] methods base
other attached packages:
[1] IlluminaHumanMethylation450kanno.ilmn12.hg19_0.6.1
[2] scales_1.4.0
[3] CMEnt_0.99.0
[4] IlluminaHumanMethylationEPICanno.ilm10b4.hg19_0.6.0
[5] org.Hs.eg.db_3.23.1
[6] TxDb.Hsapiens.UCSC.hg19.knownGene_3.22.1
[7] GenomicFeatures_1.64.0
[8] AnnotationDbi_1.74.0
[9] bsseq_1.48.0
[10] dplyr_1.2.1
[11] ggplot2_4.0.3
[12] data.table_1.18.4
[13] minfi_1.58.0
[14] bumphunter_1.54.0
[15] locfit_1.5-9.12
[16] iterators_1.0.14
[17] foreach_1.5.2
[18] Biostrings_2.80.1
[19] XVector_0.52.0
[20] SummarizedExperiment_1.42.0
[21] Biobase_2.72.0
[22] MatrixGenerics_1.24.0
[23] matrixStats_1.5.0
[24] GenomicRanges_1.64.0
[25] Seqinfo_1.2.0
[26] IRanges_2.46.0
[27] S4Vectors_0.50.1
[28] BiocGenerics_0.58.1
[29] generics_0.1.4
[30] testthat_3.3.2
[31] BiocStyle_2.40.0
loaded via a namespace (and not attached):
[1] graph_1.90.0
[2] igraph_2.3.2
[3] plotly_4.12.0
[4] ChAMPdata_2.44.0
[5] Formula_1.2-5
[6] devtools_2.5.2
[7] tidyselect_1.2.1
[8] bit_4.6.0
[9] doParallel_1.0.17
[10] clue_0.3-68
[11] lattice_0.22-9
[12] rjson_0.2.23
[13] nor1mix_1.3-3
[14] blob_1.3.0
[15] stringr_1.6.0
[16] rngtools_1.5.2
[17] S4Arrays_1.12.0
[18] base64_2.0.2
[19] dichromat_2.0-0.1
[20] scrime_1.3.7
[21] seqLogo_1.78.0
[22] png_0.1-9
[23] tinytex_0.59
[24] ggplotify_0.1.3
[25] cli_3.6.6
[26] marray_1.90.0
[27] bedr_1.1.5
[28] outliers_0.15
[29] ProtGenerics_1.44.0
[30] askpass_1.2.1
[31] multtest_2.68.0
[32] openssl_2.4.2
[33] JADE_2.0-4
[34] nleqslv_3.3.7
[35] pkgdown_2.2.0
[36] textshaping_1.0.5
[37] BiocIO_1.22.0
[38] purrr_1.2.2
[39] dendextend_1.19.1
[40] curl_7.1.0
[41] tidytree_0.4.7
[42] mime_0.13
[43] evaluate_1.0.5
[44] wateRmelon_2.18.0
[45] ComplexHeatmap_2.28.0
[46] stringi_1.8.7
[47] backports_1.5.1
[48] desc_1.4.3
[49] XML_3.99-0.23
[50] httpuv_1.6.17
[51] clusterProfiler_4.20.0
[52] magrittr_2.0.5
[53] rappdirs_0.3.4
[54] splines_4.6.0
[55] mclust_6.1.2
[56] DelayedDataFrame_1.28.0
[57] BiasedUrn_2.0.12
[58] jpeg_0.1-11
[59] doRNG_1.8.6.3
[60] ggraph_2.2.2
[61] rentrez_1.2.4
[62] IlluminaHumanMethylation450kmanifest_0.4.0
[63] DT_0.34.0
[64] sessioninfo_1.2.4
[65] DBI_1.3.0
[66] HDF5Array_1.40.0
[67] reactome.db_1.96.0
[68] jquerylib_0.1.4
[69] genefilter_1.94.0
[70] withr_3.0.2
[71] systemfonts_1.3.2
[72] class_7.3-23
[73] enrichplot_1.32.0
[74] rprojroot_2.1.1
[75] ggnewscale_0.5.2
[76] brio_1.1.5
[77] tidygraph_1.3.1
[78] sva_3.60.0
[79] isva_1.10
[80] formatR_1.14
[81] rtracklayer_1.72.0
[82] BiocManager_1.30.27
[83] Illumina450ProbeVariants.db_1.48.0
[84] htmlwidgets_1.6.4
[85] fs_2.1.0
[86] ggrepel_0.9.8
[87] biomaRt_2.68.0
[88] missMethyl_1.46.0
[89] labeling_0.4.3
[90] SparseArray_1.12.2
[91] cellranger_1.1.0
[92] shinycssloaders_1.1.0
[93] h5mread_1.4.0
[94] annotate_1.90.0
[95] VariantAnnotation_1.58.0
[96] knitr_1.51
[97] TFBSTools_1.50.0
[98] UCSC.utils_1.8.0
[99] beanplot_1.3.1
[100] TFMPvalue_1.0.0
[101] ChAMP_2.42.0
[102] annotatr_1.38.0
[103] patchwork_1.3.2
[104] caTools_1.18.3
[105] grid_4.6.0
[106] ggtree_4.2.0
[107] rhdf5_2.56.0
[108] pwalign_1.8.0
[109] R.oo_1.27.1
[110] ggiraph_0.9.6
[111] regioneR_1.44.0
[112] gridGraphics_0.5-1
[113] ellipsis_0.3.3
[114] lazyeval_0.2.3
[115] yaml_2.3.12
[116] survival_3.8-6
[117] RPMM_1.25
[118] BiocVersion_3.23.1
[119] crayon_1.5.3
[120] tweenr_2.0.3
[121] RColorBrewer_1.1-3
[122] tidyr_1.3.2
[123] later_1.4.8
[124] codetools_0.2-20
[125] base64enc_0.1-6
[126] GlobalOptions_0.1.4
[127] KEGGREST_1.52.0
[128] shape_1.4.6.1
[129] ReactomePA_1.56.0
[130] fastICA_1.2-7
[131] limma_3.68.4
[132] gdtools_0.5.1
[133] Rsamtools_2.28.0
[134] filelock_1.0.3
[135] showtext_0.9-8
[136] foreign_0.8-90
[137] pkgconfig_2.0.3
[138] xml2_1.5.2
[139] GenomicAlignments_1.48.0
[140] aplot_0.2.9
[141] hummingbird_1.22.0
[142] ape_5.8-1
[143] BSgenome_1.80.0
[144] viridisLite_0.4.3
[145] biovizBase_1.60.0
[146] gridBase_0.4-7
[147] xtable_1.8-8
[148] interp_1.1-6
[149] lumi_2.64.0
[150] plyr_1.8.9
[151] httr_1.4.8
[152] tools_4.6.0
[153] pkgbuild_1.4.8
[154] htmlTable_2.5.0
[155] checkmate_2.3.4
[156] nlme_3.1-168
[157] affy_1.90.0
[158] futile.logger_1.4.9
[159] lambda.r_1.2.4
[160] dbplyr_2.5.2
[161] ExperimentHub_3.2.0
[162] IlluminaHumanMethylationEPICmanifest_0.3.0
[163] digest_0.6.39
[164] permute_0.9-10
[165] bookdown_0.46
[166] Matrix_1.7-5
[167] farver_2.1.2
[168] tzdb_0.5.0
[169] AnnotationFilter_1.36.0
[170] reshape2_1.4.5
[171] yulab.utils_0.2.4
[172] viridis_0.6.5
[173] DirichletMultinomial_1.54.0
[174] rpart_4.1.27
[175] glue_1.8.1
[176] cachem_1.1.0
[177] bspm_0.5.8
[178] VennDiagram_1.8.2
[179] BiocFileCache_3.2.0
[180] polyclip_1.10-7
[181] methylumi_2.58.0
[182] Hmisc_5.2-5
[183] txdbmaker_1.8.0
[184] sysfonts_0.8.9
[185] pkgload_1.5.2
[186] statmod_1.5.2
[187] impute_1.86.0
[188] fontBitstreamVera_0.1.1
[189] GEOquery_2.80.0
[190] httr2_1.2.2
[191] showtextdb_3.0
[192] gson_0.1.0
[193] dmrseq_1.32.0
[194] graphlayouts_1.2.3
[195] siggenes_1.86.0
[196] gtools_3.9.5
[197] readxl_1.5.0
[198] preprocessCore_1.74.0
[199] affyio_1.82.0
[200] gridExtra_2.3
[201] shiny_1.13.0
[202] tidydr_0.0.6
[203] R.utils_2.13.0
[204] rhdf5filters_1.24.0
[205] RCurl_1.98-1.19
[206] memoise_2.0.1
[207] rmarkdown_2.31
[208] R.methodsS3_1.8.2
[209] svglite_2.2.2
[210] reshape_0.8.10
[211] fontLiberation_0.1.0
[212] illuminaio_0.54.0
[213] rstudioapi_0.18.0
[214] cluster_2.1.8.2
[215] ROC_1.88.0
[216] hms_1.1.4
[217] globaltest_5.66.0
[218] DMRcate_3.8.0
[219] colorspace_2.1-2
[220] FNN_1.1.4.1
[221] rlang_1.2.0
[222] quadprog_1.5-8
[223] BSgenome.Hsapiens.UCSC.hg19_1.4.3
[224] GenomeInfoDb_1.48.0
[225] DelayedMatrixStats_1.34.0
[226] sparseMatrixStats_1.24.0
[227] shinythemes_1.2.0
[228] ggforce_0.5.0
[229] ggtangle_0.1.2
[230] circlize_0.4.18
[231] mgcv_1.9-4
[232] xfun_0.58
[233] ggseqlogo_0.2.2
[234] e1071_1.7-17
[235] aisdk_1.4.12
[236] abind_1.4-8
[237] GOSemSim_2.38.0
[238] tibble_3.3.1
[239] treeio_1.36.1
[240] Rhdf5lib_2.0.0
[241] readr_2.2.0
[242] futile.options_1.0.1
[243] bitops_1.0-9
[244] ps_1.9.3
[245] promises_1.5.0
[246] scatterpie_0.2.6
[247] inline_0.3.21
[248] RSQLite_3.53.1
[249] qvalue_2.44.0
[250] DelayedArray_0.38.2
[251] proxy_0.4-29
[252] GO.db_3.23.1
[253] compiler_4.6.0
[254] prettyunits_1.2.0
[255] beachmat_2.28.0
[256] graphite_1.58.0
[257] Rcpp_1.1.1-1.1
[258] DNAcopy_1.86.0
[259] fontquiver_0.2.1
[260] edgeR_4.10.1
[261] AnnotationHub_4.2.0
[262] usethis_3.2.1
[263] MASS_7.3-65
[264] progress_1.2.3
[265] BiocParallel_1.46.0
[266] R6_2.6.1
[267] fastmap_1.2.0
[268] ensembldb_2.36.1
[269] enrichit_0.1.4
[270] nnet_7.3-20
[271] gtable_0.3.6
[272] KernSmooth_2.23-26
[273] strex_2.0.1
[274] latticeExtra_0.6-31
[275] deldir_2.0-4
[276] htmltools_0.5.9
[277] bit64_4.8.2
[278] lifecycle_1.0.5
[279] S7_0.2.2
[280] processx_3.9.0
[281] callr_3.8.0
[282] Gviz_1.56.0
[283] restfulr_0.0.16
[284] sass_0.4.10
[285] vctrs_0.7.3
[286] DOSE_4.6.0
[287] ggfun_0.2.0
[288] goseq_1.64.0
[289] bslib_0.11.0
[290] pillar_1.11.1
[291] magick_2.9.1
[292] otel_0.2.0
[293] combinat_0.0-8
[294] geneLenDataBase_1.48.0
[295] jsonlite_2.0.0
[296] cigarillo_1.2.0
[297] GetoptLong_1.1.1