Analyses realted to control probes from Illumina arrays, showing that fCpGs are not SNPs.

1 Load packages and fCpGs information

##
## Load necessary packages and set global options
##


library(data.table)
library(janitor)
library(dplyr)
library(ggpubr)
library(pals)
library(GenomicRanges)
library(openxlsx)
library(Biostrings)
library(IlluminaHumanMethylation450kanno.ilmn12.hg19)
library(patchwork)
library(ComplexHeatmap)
library(circlize)
library(pals)
library(SNPlocs.Hsapiens.dbSNP155.GRCh38)
library(MafH5.gnomAD.v4.0.GRCh38)

options(stringsAsFactors = F,max.print = 10000,error=NULL,
        "openxlsx.dateFormat" = "dd/mm/yyyy"
)



## load fCpGs with meth values

fcpgs.betas <- 
  fread("../Data/FMC/Final_data/beta_filtered_samples_fcpgs_laplacian.tsv",data.table = F) %>% 
  tibble::column_to_rownames(var = "V1")

fcpgs.betas[1:5,1:5]
dim(fcpgs.betas)


##load all metadata
sheets <- getSheetNames("../Revision/Data/Supplementary_Tables_revision_curated.3.xlsx")
sheets <- setNames(sheets,sheets)

fCpGs.metadata <- lapply(sheets,function(i){
  openxlsx::read.xlsx("../Revision/Data/Supplementary_Tables_revision_curated.3.xlsx",sheet = i,detectDates = T)
})

2 fCpG hg38

fcpgs.hg19.CG <- minfi::getAnnotation(IlluminaHumanMethylation450kanno.ilmn12.hg19)[rownames(fcpgs.betas),] %>% 
  as.data.frame()

fcpgs.hg19.CG  <- 
  GRanges(fcpgs.hg19.CG$chr,IRanges(fcpgs.hg19.CG$pos,fcpgs.hg19.CG$pos),strand = fcpgs.hg19.CG$strand,
          fcpgs.hg19.CG %>% select(-c(chr,pos,strand))
  )
fcpgs.hg19.CG

getSeq(BSgenome.Hsapiens.UCSC.hg19::BSgenome.Hsapiens.UCSC.hg19,fcpgs.hg19.CG) %>% as.character() %>% table
getSeq(BSgenome.Hsapiens.UCSC.hg19::BSgenome.Hsapiens.UCSC.hg19,fcpgs.hg19.CG[strand(fcpgs.hg19.CG)=="+"]) %>% as.character() %>% table
getSeq(BSgenome.Hsapiens.UCSC.hg19::BSgenome.Hsapiens.UCSC.hg19,fcpgs.hg19.CG[strand(fcpgs.hg19.CG)=="-"]) %>% as.character() %>% table

##perform liftover
hg19.to.hg38.chain <- rtracklayer::import.chain(con = "../Revision/Data/Nanopore/hg19ToHg38.over.chain")
fcpgs.hg38.CG <- rtracklayer::liftOver(x = fcpgs.hg19.CG,chain = hg19.to.hg38.chain)
fcpgs.hg38.CG <- unlist(fcpgs.hg38.CG)

length(fcpgs.hg19.CG)
length(fcpgs.hg38.CG)

fcpgs.hg19.CG$Name[which(!fcpgs.hg19.CG$Name %in% fcpgs.hg38.CG$Name)]

fcpgs.hg38.CG

getSeq(BSgenome.Hsapiens.UCSC.hg38::BSgenome.Hsapiens.UCSC.hg38,fcpgs.hg38.CG) %>% as.character() %>% table
getSeq(BSgenome.Hsapiens.UCSC.hg38::BSgenome.Hsapiens.UCSC.hg38,fcpgs.hg38.CG[strand(fcpgs.hg38.CG)=="+"]) %>% as.character() %>% table
getSeq(BSgenome.Hsapiens.UCSC.hg38::BSgenome.Hsapiens.UCSC.hg38,fcpgs.hg38.CG[strand(fcpgs.hg38.CG)=="-"]) %>% as.character() %>% table

fcpgs.hg38.CG[strand(fcpgs.hg38.CG)=="-"] %>% granges()

##liftover do not work on this CpG
fcpgs.hg38.CG[strand(fcpgs.hg38.CG)=="-"][which(getSeq(BSgenome.Hsapiens.UCSC.hg38::BSgenome.Hsapiens.UCSC.hg38,fcpgs.hg38.CG[strand(fcpgs.hg38.CG)=="-"]) %>% as.character() !="G"),]
exclude <- fcpgs.hg38.CG[strand(fcpgs.hg38.CG)=="-"]$Name[which(getSeq(BSgenome.Hsapiens.UCSC.hg38::BSgenome.Hsapiens.UCSC.hg38,fcpgs.hg38.CG[strand(fcpgs.hg38.CG)=="-"]) %>% as.character() !="G")]
exclude

fcpgs.hg38.CG <- fcpgs.hg38.CG[fcpgs.hg38.CG$Name!=exclude]
fcpgs.hg38.CG

#check nucleotides ## OK!
getSeq(BSgenome.Hsapiens.UCSC.hg38::BSgenome.Hsapiens.UCSC.hg38,fcpgs.hg38.CG[strand(fcpgs.hg38.CG)=="+"]) %>% as.character() %>% table
getSeq(BSgenome.Hsapiens.UCSC.hg38::BSgenome.Hsapiens.UCSC.hg38,fcpgs.hg38.CG[strand(fcpgs.hg38.CG)=="-"]) %>% as.character() %>% table

3 Control probes

We next load Illumina control SNP probes for each processed batch. We get the methyaltion value of the 59 control probes for all the samples (n=2,204)

data.paths <- list.files("../Data",pattern = "RGset.qs",recursive = T,full.names = T)
data.paths <- setNames(data.paths,
                       strsplit(data.paths,"/") %>% sapply(.,function(x)x[5]) %>% gsub("QC_|_RGset.qs","",.)
                       )
data.paths

ctl.snps.betas <- parallel::mclapply(data.paths,function(file.i){

  writeLines(file.i) 
  RGset <- qs::qread(file.i)
  getSnpBeta(RGset)
  
},mc.cores = 8)

sapply(ctl.snps.betas,nrow)
ctl.snps.betas$Bcells_Kulis_2015_450k %>% head
shared.ctl.snps.betas <- do.call(cbind,lapply(ctl.snps.betas,function(x)x[Reduce(intersect,lapply(ctl.snps.betas,rownames)),]))
head(shared.ctl.snps.betas);dim(shared.ctl.snps.betas)

##retain samples used in the study, with same order as emtadata
table(fCpGs.metadata$supplementary_table_1$participant_id_anonymous %in% colnames(shared.ctl.snps.betas))

shared.ctl.snps.betas <- shared.ctl.snps.betas[,fCpGs.metadata$supplementary_table_1$participant_id_anonymous]
head(shared.ctl.snps.betas);dim(shared.ctl.snps.betas)

4 SNP annotation

We next use annotation packages to annotate the minor allele frequency and SNP name of all the cntrol probes provided by Illumina.

snps <- SNPlocs.Hsapiens.dbSNP155.GRCh38
mafh5 <- MafH5.gnomAD.v4.0.GRCh38

ctl.snps.hg38 <- snpsById(snps,rownames(shared.ctl.snps.betas),
                          ifnotfound="warning",
                          genome=BSgenome.Hsapiens.UCSC.hg38::BSgenome.Hsapiens.UCSC.hg38)
# rs13369115 has merged into rs10155413, change it accordingly to get hg38 coordinates  (checks at web dbSNP)
rownames(shared.ctl.snps.betas)[which(rownames(shared.ctl.snps.betas)=="rs13369115")] <- "rs10155413"
ctl.snps.hg38 <- snpsById(snps,rownames(shared.ctl.snps.betas),
                          ifnotfound="warning",
                          genome=BSgenome.Hsapiens.UCSC.hg38::BSgenome.Hsapiens.UCSC.hg38)
ctl.snps.hg38


##overlap with rs IDs
ctl.snps.hg38.mAF <- gscores(x = mafh5,ranges = ctl.snps.hg38,pop=populations(mafh5)) 
ctl.snps.hg38.mAF$AF %>% summary

identical(ctl.snps.hg38.mAF$RefSNP_id,rownames(shared.ctl.snps.betas))

5 Heatmap control SNPs

We next plot the methylation of control SNPs as well as the retrieved information

##plot
evoflux.meth <- fread("../Revision/Data/meth_palette_evoflux.tsv")
evoflux.meth

fCpGs.metadata$supplementary_table_1 %>% dplyr::count(cell_type_annot_1,cell_type_annot_3)

# color smaples
cols.paper <- c(
  NA_values="#666666",
  HPC="#E6E6E6",
  pre.Bcell="#D5D5D5",
  NBC="#C3C3C3",
  GCB="#AEAEAE",
  tPC="#969696",
  MBC="#787878",
  bmPC="#4D4D4D",
  Bcell="#C3C3C3",
  Tcell="#F0F8FF",
  PBMCs="#FFF8DC",
  Whole_blood="#CDC8B1",
  "Whole blood"="#CDC8B1",
  Normal_lymphoid_cell="#D5D5D5",
  Normal_myeloid_cell="#E6E6FA",
  "T-ALL"="#CD3333",
  "T-ALL-remission"="#C7A5A5",
  "T-ALL-relapse"="#CD3333",
  "B-ALL"="#E69F00",
  "B-ALL-remission"="#D8CAAB",
  "B-ALL-relapse"="#E69F00",
  MCL="#F0E442",
  C1="#F5D51B",
  cMCL="#F5D51B",
  C2="#0072B2",
  nnMCL="#0072B2",
  "DLBCL-NOS"="#56B4E9",
  MBL="#5A9A89",
  CLL="#009E73",
  RT="#02C590",
  unmutated="#e65100",
  mutated="#361379",
  nCLL="#006E93",
  iCLL="#FDC010",
  mCLL="#963736",
  Disease.Unclassified="#CCCCCC",
  MGUS="#BF99AE",
  MM="#CC79A7"
)



ht_opt$legend_grid_width <- unit(2,"mm")
ht_opt$legend_grid_height <-unit(2,"mm")
ht_opt$legend_labels_gp <- gpar(fontsize=5)
ht_opt$legend_title_gp <- gpar(fontsize=5)
ht_opt$heatmap_column_title_gp <- gpar(fontsize=5)
ht_opt$heatmap_row_title_gp <- gpar(fontsize=5)
ht_opt$heatmap_row_names_gp <- gpar(fontsize=5)
ht_opt$heatmap_column_names_gp <- gpar(fontsize=5)
ht_opt$HEATMAP_LEGEND_PADDING <- unit(1,"mm")
ht_opt$ANNOTATION_LEGEND_PADDING <- unit(1,"mm")
ht_opt$legend_gap <- unit(c(1,1),"mm")
ht_opt$fast_hclust <- T



h.ctl.snps <- Heatmap(shared.ctl.snps.betas,
                       col = evoflux.meth$color,
                       name="DNA methylation",
                       column_title = paste0("Control SNPs from Illumina 450k/EPIC arrays (N=",nrow(shared.ctl.snps.betas),")"),
                       row_title = paste0("N=",nrow(shared.ctl.snps.betas)),
                       heatmap_legend_param = list(direction="horizontal"),
                       clustering_distance_columns = "euclidean",
                       clustering_method_columns = "single",
                       show_column_names = F,
                       show_row_names = F,
                       row_dend_gp = gpar(lwd=0.1),
                       column_dend_gp = gpar(lwd=0.1),
                       raster_quality = 10,
                       top_annotation = HeatmapAnnotation(annot2=factor(case_when(fCpGs.metadata$supplementary_table_1$cell_type_annot_1!="PBMCs" & 
                                                                                    fCpGs.metadata$supplementary_table_1$cell_type_annot_1!="Whole_blood" & 
                                                                                    fCpGs.metadata$supplementary_table_1$cell_type_annot_1!="Normal_lymphoid_cell" &
                                                                                    fCpGs.metadata$supplementary_table_1$cell_type_annot_1!="B-ALL-remission" &
                                                                                    fCpGs.metadata$supplementary_table_1$cell_type_annot_1!="T-ALL-remission" ~ "Lymphoid tumour",
                                                                                  .default = "Healthy sample/Blood from remission")
                                                                        ),
                                                          annot=factor(fCpGs.metadata$supplementary_table_1$cell_type_annot_1,
                                                                       levels = names(cols.paper)[names(cols.paper) %in% fCpGs.metadata$supplementary_table_1$cell_type_annot_1]),
                                                          col=list(annot=cols.paper,
                                                                   annot2=c("Healthy sample/Blood from remission"="grey0","Lymphoid tumour"="grey90")
                                                                   ),
                                                          show_annotation_name = F,
                                                          annotation_label = "Samples",
                                                          simple_anno_size = unit(3,"mm"),
                                                          annotation_legend_param = list(direction="horizontal",nrow=3)
                       ),
                       right_annotation = HeatmapAnnotation(which="row",
                                                            mAF=ctl.snps.hg38.mAF$AF,
                                                            col=list(mAF=colorRamp2(seq(min(ctl.snps.hg38.mAF$AF,na.rm = T),
                                                                                        max(ctl.snps.hg38.mAF$AF,na.rm = T),
                                                                                        length.out=100
                                                            ),
                                                            colors = brewer.blues(100)
                                                            )
                                                            ),
                                                            na_col = "grey45",
                                                            show_annotation_name = F,
                                                            # annotation_name_side = "left",
                                                            show_legend = T,
                                                            annotation_label = "mAF reporeted in gnomAD.v4.0",
                                                            annotation_name_gp = gpar(fontsize=5),
                                                            simple_anno_size = unit(2,"mm"),
                                                            annotation_legend_param = list(direction="horizontal")
                       )
)

draw(h.ctl.snps,
     heatmap_legend_side = "bottom",
     annotation_legend_side = "bottom"
     )

6 Heatmap fCpGs

We next plot the methylation of 59 random fCpGs for comparison, and see a completely distinct scenario.

##random. 59 fCPGs
set.seed(123) # for reproducibility
fCpGs.59 <- sample(x = rownames(fcpgs.betas),size = 59,replace = F)
fCpGs.59

h.fCpGs.59 <- Heatmap(fcpgs.betas[fCpGs.59,],
                   col = evoflux.meth$color,
                   name="DNA methylation",
                   column_title = paste0("59 random Pan-lymphoid fCpGs (N=",length(fCpGs.59),")"),
                   row_title = paste0("N=",length(fCpGs.59)),
                   heatmap_legend_param = list(direction="horizontal"),
                   clustering_distance_columns = "euclidean",
                   clustering_method_columns = "single",
                   show_column_names = F,
                   show_row_names = F,
                   row_dend_gp = gpar(lwd=0.1),
                   column_dend_gp = gpar(lwd=0.1),
                   raster_quality = 10,
                   top_annotation = HeatmapAnnotation(annot=factor(fCpGs.metadata$supplementary_table_1$cell_type_annot_1,
                                                                   levels = names(cols.paper)[names(cols.paper) %in% fCpGs.metadata$supplementary_table_1$cell_type_annot_1]),
                                                      col=list(annot=cols.paper),
                                                      show_annotation_name = F,
                                                      annotation_label = "Samples",
                                                      simple_anno_size = unit(3,"mm"),
                                                      annotation_legend_param = list(direction="horizontal",nrow=3)
                   )
)

draw(h.fCpGs.59,
     heatmap_legend_side = "bottom",
     annotation_legend_side = "bottom"
)

7 Histrograms SNPs vs fCpGs

We next plot example histograms in normal lymphoid cells of SNP control probes vs 59 random fCPGs, showing very distinct distributions.

## plot histogram distributions
shared.ctl.snps.betas %>% dim


fCpGs.metadata$supplementary_table_1 %>% dplyr::count(cell_type_annot_1)

identical(colnames(shared.ctl.snps.betas),fCpGs.metadata$supplementary_table_1$participant_id_anonymous)


shared.ctl.snps.betas %>% 
  as.data.frame() %>% 
  select( fCpGs.metadata$supplementary_table_1 %>% 
            filter(cell_type_annot_1=="PBMCs" | cell_type_annot_1=="Whole_blood" 
                   | cell_type_annot_1=="Normal_lymphoid_cell"
            ) %>% 
            pull(participant_id_anonymous)
          
  ) %>% 
  reshape2::melt() %>% 
  mutate(fill=cut(value,breaks = seq(0,1,length.out=101),include.lowest = T,labels = 1:100)) %>% 
  ggplot(aes(x=value))+
  geom_histogram(fill="grey70")+
  coord_cartesian(ylim = c(0,15))+
  # scale_fill_manual(values = setNames(evoflux.meth$color,1:100))+
  facet_wrap(~variable,nrow = 8,ncol = 11,
             # scales = "free_y"
  )+
  ggtitle("Control SNPs (N=59) from Illumina arrays (shared probes 450k & EPIC) in normal lymphoid samples")+
  theme_bw()+
  theme(text = element_text(size = 4),
        panel.grid = element_blank(),
        legend.position = "none",
        legend.margin = margin(0,0,0,0),
        plot.margin = margin(0,0,0,0),
        line = element_line(linewidth = 0.1),
        strip.placement = "outside",
        strip.background = element_blank(),
        plot.background = element_blank(),
        panel.background = element_blank(),
        panel.spacing = unit(0.2,"pt"),
        axis.title.y = element_text(size = 6),
        axis.text.x = element_text(angle = 90,hjust = 1,vjust = 1,size = 4,margin = margin(0,0,0,0,"pt")),
        strip.text.x = element_text(angle = 0,size = 4,vjust = 0.5,hjust = 0.5),
        legend.key.size = unit(5,"pt")
  ) |
  fcpgs.betas[fCpGs.59,] %>% 
  as.data.frame() %>% 
  select( fCpGs.metadata$supplementary_table_1 %>% 
            filter(cell_type_annot_1=="PBMCs" | cell_type_annot_1=="Whole_blood" 
                   | cell_type_annot_1=="Normal_lymphoid_cell"
            ) %>% 
            pull(participant_id_anonymous)
          
  ) %>% 
  reshape2::melt() %>% 
  mutate(fill=cut(value,breaks = seq(0,1,length.out=101),include.lowest = T,labels = 1:100)) %>% 
  ggplot(aes(x=value))+
  geom_histogram(fill="grey70")+
  coord_cartesian(ylim = c(0,15))+
  # scale_fill_manual(values = setNames(evoflux.meth$color,1:100))+
  facet_wrap(~variable,nrow = 8,ncol = 11,
             # scales = "free_y"
  )+
  theme_bw()+
  ggtitle("Random fCpGs (N=59) in normal lymphoid samples")+
  theme(text = element_text(size = 4),
        panel.grid = element_blank(),
        legend.position = "none",
        legend.margin = margin(0,0,0,0),
        plot.margin = margin(0,0,0,0),
        line = element_line(linewidth = 0.1),
        strip.placement = "outside",
        strip.background = element_blank(),
        plot.background = element_blank(),
        panel.background = element_blank(),
        panel.spacing = unit(0.2,"pt"),
        axis.title.y = element_text(size = 6),
        axis.text.x = element_text(angle = 90,hjust = 1,vjust = 1,size = 4,margin = margin(0,0,0,0,"pt")),
        strip.text.x = element_text(angle = 0,size = 4,vjust = 0.5,hjust = 0.5),
        legend.key.size = unit(5,"pt")
  )

8 Intermediate values

We see how SNPs and fCpGs have a completely distinc distribution of intermediate methylation values.

##
##Plot percentage of intermediate meth values
##

identical(colnames(shared.ctl.snps.betas),fCpGs.metadata$supplementary_table_1$participant_id_anonymous)

fCpGs.metadata$supplementary_table_1 %>% dplyr::count(cell_type_annot_1,cell_type_annot_3)

sample.indx <- 
  split(seq_along(fCpGs.metadata$supplementary_table_1$participant_id_anonymous),
      fCpGs.metadata$supplementary_table_1$cell_type_annot_3
      )


snps.pct.intermediate <- 
  lapply(sample.indx,function(indx){
  
  mat <- apply(shared.ctl.snps.betas[,indx],2,function(x){
    
    (x>0.2 & x <0.4) | (x>0.6 & x <0.8)
    
  })
  
  res <- rowMeans(mat) %>% sort()*100
  return(res)
})


identical(colnames(fcpgs.betas),fCpGs.metadata$supplementary_table_1$participant_id_anonymous)
fCpGs.pct.intermediate <- 
  lapply(sample.indx,function(indx){
    
    mat <- apply(fcpgs.betas[,indx],2,function(x){
      
      (x>0.2 & x <0.4) | (x>0.6 & x <0.8)
      
    })
    
    res <- rowMeans(mat) %>% sort()*100
    return(res)
  })


##
bind_rows(snps.pct.intermediate %>% reshape2::melt() %>% mutate(CpGs="Control SNPs"),
                    fCpGs.pct.intermediate %>% reshape2::melt() %>% mutate(CpGs="fCpGs")
                    ) %>% 
  rename(L1="samples",
         value="pct"
         ) %>% 
  mutate(samples=factor(samples,
                        levels=names(cols.paper)[names(cols.paper) %in% fCpGs.metadata$supplementary_table_1$cell_type_annot_3])
         ) %>% 
  ggplot(aes(x = CpGs,
             y=pct
             ))+
  geom_boxplot(aes(fill=samples),lwd=0.2,outlier.size = 0.5)+
  facet_grid(~samples)+
  stat_compare_means(method = "t.test",size=1)+
  xlab(NULL)+
  ylab("Percentange (%) of CpGs in intermediate peaks (x>0.2 & x <0.4) | (x>0.6 & x <0.8)")+
  scale_fill_manual(values = cols.paper)+
  theme_classic()+
  theme(text = element_text(colour = "grey0",size = 5),
        panel.grid.major = element_line(linewidth = 0.075),
        # panel.grid.minor.x = element_line(linewidth = 0.025),
        strip.placement = "out",
        strip.background = element_blank(),
        strip.text =  element_text(angle = 0),
        plot.margin = unit(c(0,0,0,0),"pt"),
        line=element_line(linewidth = 0.1),
        legend.position = "none",
        legend.box.margin=margin(-5,-5,-5,-5),
        # legend.justification="top",
        axis.text.x = element_text(angle = 90,vjust = 1,hjust = 1),
        legend.text = element_text(angle = 90,vjust = 0.5,hjust = 0.5),
        plot.background =element_blank(),
        legend.key.size = unit(5,"pt")
  )

9 Longitudinal samples

We next follow our analsyes plotting the methylation dynamics of SNPs vs fCpGs in longitudinal samples experiencing (sub)clonal evolution in ALL and CLL, thorugh diagnosis, relapse or Richter transformation (in CLL). While we see the same methylation over time in control SNPs, we observe how fCpG methylation values vary hugely over time during (sub)clonal evolution, even with only 59 fCpGs.

9.1 CLL

9.1.1 Control SNPs

## CLL

rt.meta <- 
  fCpGs.metadata$supplementary_table_1 %>% 
  arrange(same_sample_id_new,sample_timepoints,factor(platform,levels=c("Illumina-EPIC","Illumina-450k"))) %>% 
  filter(grepl("SCLL-012|SCLL-019",participant_id_new),
  )
rt.meta
rt.meta %>% filter(duplicated(same_sample_id_new) | duplicated(same_sample_id_new,fromLast=T)) %>% 
  select(sample_id,sample_id_new,sample_timepoints,platform,sampling_time_disease_state)

rt.meta <- 
  rt.meta %>% 
  filter(!(sample_id_new=="012-02-1TD" & platform=="Illumina-450k"),
         !(sample_id_new=="019-0047-01TD" & platform=="Illumina-450k")
  ) %>% 
  mutate(case=gsub("SCLL-|0","",participant_id_new))

rt.meta %>% 
  select(sample_id_new,case,sampling_time_disease_state,sample_timepoints,platform)

rt.meta %>% select(case,sample_timepoints)
comparisons <- 
  paste0(rt.meta$case[-nrow(rt.meta)],"_",
         rt.meta$sample_timepoints[-nrow(rt.meta)],"_",
         rt.meta$sample_timepoints[-1],"_",
         gsub("Illumina-","",rt.meta$platform[-nrow(rt.meta)]),
         "_",
         gsub("Illumina-","",rt.meta$platform[-1])
  )
comparisons
comparisons <- comparisons[comparisons!="12_T4_T1_EPIC_450k"]
comparisons <- setNames(comparisons,comparisons)
comparisons


##plot ctl SNPs
rt.ctl.snps.betas <- 
  shared.ctl.snps.betas[,rt.meta$participant_id_anonymous] 

dim(rt.ctl.snps.betas)

df <- lapply(comparisons, function(comp.i){
  
  case.i <- strsplit(comp.i,"_")[[1]][1]
  timepoint.1 <- strsplit(comp.i,"_")[[1]][2]
  timepoint.2 <- strsplit(comp.i,"_")[[1]][3]
  
  sample.t1 <-
    rt.meta %>% 
    filter(case==case.i,sample_timepoints==timepoint.1) %>% 
    pull(participant_id_anonymous)
  
  sample.t2 <-
    rt.meta %>% 
    filter(case==case.i,sample_timepoints==timepoint.2) %>% 
    pull(participant_id_anonymous)
  
  
  dat <- data.frame(case=case.i,
                    comparison=comp.i,
                    samples=paste0("sample.t1:",sample.t1,", sample.t2:",sample.t2),
                    # cpgs_diff_direction=rt.ctl.snps.betas[,sample.t2]-rt.ctl.snps.betas[,sample.t1],
                    cpgs_diff_abs=abs((rt.ctl.snps.betas[,sample.t2]-rt.ctl.snps.betas[,sample.t1])),
                    rt.ctl.snps.betas[,c(sample.t1,sample.t2)]
  )
  colnames(dat)[(ncol(dat)-1):ncol(dat)] <- c("meth.T1","meth.T2")
  
  return(dat)
})

df <- do.call(rbind,df)

head(df)


## Loop over each case
for(case.i in unique(df$case)){
  
  p <- 
    df %>% 
    filter(case==case.i) %>%
    mutate(cpgs_diff_abs=case_when(cpgs_diff_abs>= 0.25 ~ 0.25,
                                   .default = cpgs_diff_abs
    )
    ) %>% 
    ggplot(aes(x=meth.T2,
               y=meth.T1,
               fill=cpgs_diff_abs
    )
    )+
    
    geom_point(pch=21,stroke=0.1,size=0.6)+
    scale_fill_gradientn("Absolute methylation\ndifference",limits=c(0,0.25),
                         colours = viridis(100) %>% rev()
    )+
    stat_cor(size=1)+
    facet_grid(~comparison)+
    theme_classic()+
    theme(text = element_text(colour = "grey0",size = 5),
          panel.grid.major = element_line(linewidth = 0.075),
          # panel.grid.minor.x = element_line(linewidth = 0.025),
          strip.placement = "out",
          strip.background = element_blank(),
          strip.text =  element_text(angle = 0),
          plot.margin = unit(c(0,0,0,0),"pt"),
          line=element_line(linewidth = 0.1),
          legend.position = "bottom",
          legend.box.margin=margin(-5,-5,-5,-5),
          # legend.justification="top",
          legend.text = element_text(angle = 90,vjust = 0.5,hjust = 0.5),
          plot.background =element_blank(),
          legend.key.size = unit(5,"pt")
    )
  print(p)
  
}

9.1.2 Random fCpGs

##plot  random 59 fCPGs
##plot ctl SNPs
set.seed(123)
fCpGs.59 <- sample(x = rownames(fcpgs.betas),size = 59,replace = F)
fCpGs.59
random.59.fCpGs.betas <- 
  fcpgs.betas[fCpGs.59,rt.meta$participant_id_anonymous] 

dim(random.59.fCpGs.betas)

df <- lapply(comparisons, function(comp.i){
  
  case.i <- strsplit(comp.i,"_")[[1]][1]
  timepoint.1 <- strsplit(comp.i,"_")[[1]][2]
  timepoint.2 <- strsplit(comp.i,"_")[[1]][3]
  
  sample.t1 <-
    rt.meta %>% 
    filter(case==case.i,sample_timepoints==timepoint.1) %>% 
    pull(participant_id_anonymous)
  
  sample.t2 <-
    rt.meta %>% 
    filter(case==case.i,sample_timepoints==timepoint.2) %>% 
    pull(participant_id_anonymous)
  
  
  dat <- data.frame(case=case.i,
                    comparison=comp.i,
                    samples=paste0("sample.t1:",sample.t1,", sample.t2:",sample.t2),
                    cpgs_diff_abs=abs((random.59.fCpGs.betas[,sample.t2]-random.59.fCpGs.betas[,sample.t1])),
                    random.59.fCpGs.betas[,c(sample.t1,sample.t2)]
  )
  colnames(dat)[(ncol(dat)-1):ncol(dat)] <- c("meth.T1","meth.T2")
  
  return(dat)
})

df <- do.call(rbind,df)

head(df)


## loop over each case

for(case.i in unique(df$case)){
  
  p <- 
    df %>% 
    filter(case==case.i) %>%
    mutate(cpgs_diff_abs=case_when(cpgs_diff_abs>= 0.25 ~ 0.25,
                                   .default = cpgs_diff_abs
    )
    ) %>% 
    ggplot(aes(x=meth.T2,
               y=meth.T1,
               fill=cpgs_diff_abs
    )
    )+
    
    geom_point(pch=21,stroke=0.1,size=0.6)+
    scale_fill_gradientn("Absolute methylation\ndifference",limits=c(0,0.25),
                         colours = viridis(100) %>% rev()
    )+
    stat_cor(size=1)+
    facet_grid(~comparison)+
    theme_classic()+
    theme(text = element_text(colour = "grey0",size = 5),
          panel.grid.major = element_line(linewidth = 0.075),
          # panel.grid.minor.x = element_line(linewidth = 0.025),
          strip.placement = "out",
          strip.background = element_blank(),
          strip.text =  element_text(angle = 0),
          plot.margin = unit(c(0,0,0,0),"pt"),
          line=element_line(linewidth = 0.1),
          legend.position = "bottom",
          legend.box.margin=margin(-5,-5,-5,-5),
          # legend.justification="top",
          legend.text = element_text(angle = 90,vjust = 0.5,hjust = 0.5),
          plot.background =element_blank(),
          legend.key.size = unit(5,"pt")
    )
  print(p)
  
}

9.2 ALL, 2 timepoints

9.2.1 Control SNPs

fCpGs.metadata$supplementary_table_1 %>% head
fCpGs.metadata$supplementary_table_1 %>% dplyr::count(cell_type_annot_3)

ALL.summarized <- 
  fCpGs.metadata$supplementary_table_1 %>% 
  filter(cell_type_annot_3=="B-ALL" | cell_type_annot_3=="B-ALL-remission" | cell_type_annot_3=="B-ALL-relapse",
         !is.na(same_sample_id_new)
         ) %>%
  group_by(same_sample_id_new) %>% 
  summarise(n=n(),
            timepoints=list((sample_timepoints)),
            unique.timepoints=list(unique(sample_timepoints))
  ) %>%
  filter(n>=2) %>% 
  arrange(desc(n))

ALL.summarized
ALL.summarized$unique.timepoints[7]
ALL.summarized %>% tail
table(sapply(ALL.summarized$unique.timepoints,length)==ALL.summarized$n)


ALL.meta <- 
  fCpGs.metadata$supplementary_table_1 %>% 
  filter(same_sample_id_new %in% ALL.summarized$same_sample_id_new) %>% 
  arrange(same_sample_id_new,sample_timepoints) %>% 
  mutate(samples.factors=factor(same_sample_id_new,levels=ALL.summarized$same_sample_id_new))
ALL.meta %>% head
ALL.meta %>% dim

comparisons <- lapply(split(seq_along(ALL.meta$samples.factors),ALL.meta$samples.factors),function(indx){
  
  dat <- ALL.meta[indx,]
  
  res <- paste0(dat$same_sample_anonymous,"_",
         dat$sample_timepoints[-nrow(dat)],"_",
         dat$sample_timepoints[-1]
         )
  res <- setNames(res,res)
  
}) 
comparisons <- unlist(comparisons,use.names = F)
comparisons <- setNames(comparisons,comparisons)
comparisons


##plot ctl SNPs
ALL.ctl.snps.betas <- 
  shared.ctl.snps.betas[,ALL.meta$participant_id_anonymous] 

dim(ALL.ctl.snps.betas)

df <- lapply(comparisons, function(comp.i){
  
  case.i <- strsplit(comp.i,"_T")[[1]][1]
  timepoint.1 <- paste0("T",strsplit(comp.i,"_T")[[1]][2])
  timepoint.2 <- paste0("T",strsplit(comp.i,"_T")[[1]][3])
  
  sample.t1 <-
    ALL.meta %>% 
    filter(same_sample_anonymous==case.i,sample_timepoints==timepoint.1) %>% 
    pull(participant_id_anonymous)
  
  sample.t2 <-
    ALL.meta %>% 
    filter(same_sample_anonymous==case.i,sample_timepoints==timepoint.2) %>% 
    pull(participant_id_anonymous)
  
  
  dat <- data.frame(case=case.i,
                    comparison=comp.i,
                    samples=paste0("sample.t1:",sample.t1,", sample.t2:",sample.t2),
                    # cpgs_diff_direction=ALL.ctl.snps.betas[,sample.t2]-ALL.ctl.snps.betas[,sample.t1],
                    cpgs_diff_abs=abs((ALL.ctl.snps.betas[,sample.t2]-ALL.ctl.snps.betas[,sample.t1])),
                    ALL.ctl.snps.betas[,c(sample.t1,sample.t2)]
  )
  colnames(dat)[(ncol(dat)-1):ncol(dat)] <- c("meth.T1","meth.T2")
  
  return(dat)
})

df <- do.call(rbind,df)

head(df)

df %>% dplyr::count(case)


##plot

for(case.i in unique(df$case)){
  
  p <- 
    df %>% 
    filter(case==case.i) %>%
    mutate(cpgs_diff_abs=case_when(cpgs_diff_abs>= 0.25 ~ 0.25,
                                   .default = cpgs_diff_abs
    )
    ) %>% 
    ggplot(aes(x=meth.T2,
               y=meth.T1,
               fill=cpgs_diff_abs
    )
    )+
    
    geom_point(pch=21,stroke=0.1,size=0.6)+
    scale_fill_gradientn("Absolute methylation\ndifference",limits=c(0,0.25),
                         colours = viridis(100) %>% rev()
    )+
    stat_cor(size=1)+
    facet_grid(~comparison)+
    theme_classic()+
    theme(text = element_text(colour = "grey0",size = 5),
          panel.grid.major = element_line(linewidth = 0.075),
          # panel.grid.minor.x = element_line(linewidth = 0.025),
          strip.placement = "out",
          strip.background = element_blank(),
          strip.text =  element_text(angle = 0,size=4),
          plot.margin = unit(c(0,0,0,0),"pt"),
          line=element_line(linewidth = 0.1),
          legend.position = "bottom",
          legend.box.margin=margin(-5,-5,-5,-5),
          # legend.justification="top",
          legend.text = element_text(angle = 90,vjust = 0.5,hjust = 0.5),
          plot.background =element_blank(),
          legend.key.size = unit(5,"pt")
    )
  print(p)
  
}

9.2.2 Random fCpGs

#plot 59 random fCpGs
##plot ctl SNPs
set.seed(123)
fCpGs.59 <- sample(x = rownames(fcpgs.betas),size = 59,replace = F)
fCpGs.59
random.59.fCpGs.betas <- 
  fcpgs.betas[fCpGs.59,ALL.meta$participant_id_anonymous] 

dim(random.59.fCpGs.betas)

df <- lapply(comparisons, function(comp.i){
  
  case.i <- strsplit(comp.i,"_T")[[1]][1]
  timepoint.1 <- paste0("T",strsplit(comp.i,"_T")[[1]][2])
  timepoint.2 <- paste0("T",strsplit(comp.i,"_T")[[1]][3])
  
  sample.t1 <-
    ALL.meta %>% 
    filter(same_sample_anonymous==case.i,sample_timepoints==timepoint.1) %>% 
    pull(participant_id_anonymous)
  
  sample.t2 <-
    ALL.meta %>% 
    filter(same_sample_anonymous==case.i,sample_timepoints==timepoint.2) %>% 
    pull(participant_id_anonymous)
  
  
  dat <- data.frame(case=case.i,
                    comparison=comp.i,
                    samples=paste0("sample.t1:",sample.t1,", sample.t2:",sample.t2),
                    # cpgs_diff_direction=random.59.fCpGs.betas[,sample.t2]-random.59.fCpGs.betas[,sample.t1],
                    cpgs_diff_abs=abs((random.59.fCpGs.betas[,sample.t2]-random.59.fCpGs.betas[,sample.t1])),
                    random.59.fCpGs.betas[,c(sample.t1,sample.t2)]
  )
  colnames(dat)[(ncol(dat)-1):ncol(dat)] <- c("meth.T1","meth.T2")
  
  return(dat)
})

df <- do.call(rbind,df)

head(df)

df %>% dplyr::count(case)


##plot

for(case.i in unique(df$case)){
  
  p <- 
    df %>% 
    filter(case==case.i) %>%
    mutate(cpgs_diff_abs=case_when(cpgs_diff_abs>= 0.25 ~ 0.25,
                                   .default = cpgs_diff_abs
    )
    ) %>% 
    ggplot(aes(x=meth.T2,
               y=meth.T1,
               fill=cpgs_diff_abs
    )
    )+
    
    geom_point(pch=21,stroke=0.1,size=0.6)+
    scale_fill_gradientn("Absolute methylation\ndifference",limits=c(0,0.25),
                         colours = viridis(100) %>% rev()
    )+
    stat_cor(size=1)+
    facet_grid(~comparison)+
    theme_classic()+
    theme(text = element_text(colour = "grey0",size = 5),
          panel.grid.major = element_line(linewidth = 0.075),
          # panel.grid.minor.x = element_line(linewidth = 0.025),
          strip.placement = "out",
          strip.background = element_blank(),
          strip.text =  element_text(angle = 0,size=4),
          plot.margin = unit(c(0,0,0,0),"pt"),
          line=element_line(linewidth = 0.1),
          legend.position = "bottom",
          legend.box.margin=margin(-5,-5,-5,-5),
          # legend.justification="top",
          legend.text = element_text(angle = 90,vjust = 0.5,hjust = 0.5),
          plot.background =element_blank(),
          legend.key.size = unit(5,"pt")
    )
  print(p)
  
}

9.3 ALL, 3 timepoints

9.3.1 Control SNPs

fCpGs.metadata$supplementary_table_1 %>% head
fCpGs.metadata$supplementary_table_1 %>% dplyr::count(cell_type_annot_3)

ALL.summarized <- 
  fCpGs.metadata$supplementary_table_1 %>% 
  filter(cell_type_annot_3=="B-ALL" | cell_type_annot_3=="B-ALL-remission" | cell_type_annot_3=="B-ALL-relapse",
         !is.na(same_sample_id_new)
  ) %>%
  group_by(same_sample_id_new) %>% 
  summarise(n=n(),
            timepoints=list((sample_timepoints)),
            unique.timepoints=list(unique(sample_timepoints))
  ) %>%
  filter(n>=2) %>% 
  arrange(desc(n))

ALL.summarized
ALL.summarized$unique.timepoints[7]
ALL.summarized %>% tail
table(sapply(ALL.summarized$unique.timepoints,length)==ALL.summarized$n)


ALL.meta <- 
  fCpGs.metadata$supplementary_table_1 %>% 
  filter(same_sample_id_new %in% ALL.summarized$same_sample_id_new) %>% 
  arrange(same_sample_id_new,sample_timepoints) %>% 
  mutate(samples.factors=factor(same_sample_id_new,levels=ALL.summarized$same_sample_id_new))
ALL.meta %>% head
ALL.meta %>% dim

comparisons <- lapply(split(seq_along(ALL.meta$samples.factors),ALL.meta$samples.factors),function(indx){
  
  dat <- ALL.meta[indx,]
  
  res <- paste0(dat$same_sample_id_new,"_",
                dat$sample_timepoints[-nrow(dat)],"_",
                dat$sample_timepoints[-1]
  )
  res <- setNames(res,res)
  
}) 
comparisons <- unlist(comparisons,use.names = F)
comparisons <- setNames(comparisons,comparisons)
comparisons


##plot ctl SNPs
ALL.ctl.snps.betas <- 
  shared.ctl.snps.betas[,ALL.meta$participant_id_anonymous] 

dim(ALL.ctl.snps.betas)

df <- lapply(comparisons, function(comp.i){
  
  case.i <- strsplit(comp.i,"_T")[[1]][1]
  timepoint.1 <- paste0("T",strsplit(comp.i,"_T")[[1]][2])
  timepoint.2 <- paste0("T",strsplit(comp.i,"_T")[[1]][3])
  
  sample.t1 <-
    ALL.meta %>% 
    filter(same_sample_id_new==case.i,sample_timepoints==timepoint.1) %>% 
    pull(participant_id_anonymous)
  
  sample.t2 <-
    ALL.meta %>% 
    filter(same_sample_id_new==case.i,sample_timepoints==timepoint.2) %>% 
    pull(participant_id_anonymous)
  
  
  dat <- data.frame(case=case.i,
                    comparison=comp.i,
                    samples=paste0("sample.t1:",sample.t1,", sample.t2:",sample.t2),
                    # cpgs_diff_direction=ALL.ctl.snps.betas[,sample.t2]-ALL.ctl.snps.betas[,sample.t1],
                    cpgs_diff_abs=abs((ALL.ctl.snps.betas[,sample.t2]-ALL.ctl.snps.betas[,sample.t1])),
                    ALL.ctl.snps.betas[,c(sample.t1,sample.t2)]
  )
  colnames(dat)[(ncol(dat)-1):ncol(dat)] <- c("meth.T1","meth.T2")
  
  return(dat)
})

df <- do.call(rbind,df)

head(df)

df %>% dplyr::count(case)


##plot

for(case.i in unique(df$case)){
  
  p <- 
    df %>% 
    filter(case==case.i) %>%
    mutate(cpgs_diff_abs=case_when(cpgs_diff_abs>= 0.25 ~ 0.25,
                                   .default = cpgs_diff_abs
    )
    ) %>% 
    ggplot(aes(x=meth.T2,
               y=meth.T1,
               fill=cpgs_diff_abs
    )
    )+
    
    geom_point(pch=21,stroke=0.1,size=0.6)+
    scale_fill_gradientn("Absolute methylation\ndifference",limits=c(0,0.25),
                         colours = viridis(100) %>% rev()
    )+
    stat_cor(size=1)+
    facet_grid(~comparison)+
    theme_classic()+
    theme(text = element_text(colour = "grey0",size = 5),
          panel.grid.major = element_line(linewidth = 0.075),
          # panel.grid.minor.x = element_line(linewidth = 0.025),
          strip.placement = "out",
          strip.background = element_blank(),
          strip.text =  element_text(angle = 0,size=4),
          plot.margin = unit(c(0,0,0,0),"pt"),
          line=element_line(linewidth = 0.1),
          legend.position = "bottom",
          legend.box.margin=margin(-5,-5,-5,-5),
          # legend.justification="top",
          legend.text = element_text(angle = 90,vjust = 0.5,hjust = 0.5),
          plot.background =element_blank(),
          legend.key.size = unit(5,"pt")
    )
  print(p)
  
}

9.3.2 Random fCpGs

##plot 59 random fCpGs
##plot ctl SNPs
set.seed(123)
fCpGs.59 <- sample(x = rownames(fcpgs.betas),size = 59,replace = F)
fCpGs.59
random.59.fCpGs.betas <- 
  fcpgs.betas[fCpGs.59,ALL.meta$participant_id_anonymous] 

dim(random.59.fCpGs.betas)

df <- lapply(comparisons, function(comp.i){
  
  case.i <- strsplit(comp.i,"_T")[[1]][1]
  timepoint.1 <- paste0("T",strsplit(comp.i,"_T")[[1]][2])
  timepoint.2 <- paste0("T",strsplit(comp.i,"_T")[[1]][3])
  
  sample.t1 <-
    ALL.meta %>% 
    filter(same_sample_id_new==case.i,sample_timepoints==timepoint.1) %>% 
    pull(participant_id_anonymous)
  
  sample.t2 <-
    ALL.meta %>% 
    filter(same_sample_id_new==case.i,sample_timepoints==timepoint.2) %>% 
    pull(participant_id_anonymous)
  
  
  dat <- data.frame(case=case.i,
                    comparison=comp.i,
                    samples=paste0("sample.t1:",sample.t1,", sample.t2:",sample.t2),
                    # cpgs_diff_direction=random.59.fCpGs.betas[,sample.t2]-random.59.fCpGs.betas[,sample.t1],
                    cpgs_diff_abs=abs((random.59.fCpGs.betas[,sample.t2]-random.59.fCpGs.betas[,sample.t1])),
                    random.59.fCpGs.betas[,c(sample.t1,sample.t2)]
  )
  colnames(dat)[(ncol(dat)-1):ncol(dat)] <- c("meth.T1","meth.T2")
  
  return(dat)
})

df <- do.call(rbind,df)

head(df)

df %>% dplyr::count(case)


##plot

for(case.i in unique(df$case)){
  
  p <- 
    df %>% 
    filter(case==case.i) %>%
    mutate(cpgs_diff_abs=case_when(cpgs_diff_abs>= 0.25 ~ 0.25,
                                   .default = cpgs_diff_abs
    )
    ) %>% 
    ggplot(aes(x=meth.T2,
               y=meth.T1,
               fill=cpgs_diff_abs
    )
    )+
    
    geom_point(pch=21,stroke=0.1,size=0.6)+
    scale_fill_gradientn("Absolute methylation\ndifference",limits=c(0,0.25),
                         colours = viridis(100) %>% rev()
    )+
    stat_cor(size=1)+
    facet_grid(~comparison)+
    theme_classic()+
    theme(text = element_text(colour = "grey0",size = 5),
          panel.grid.major = element_line(linewidth = 0.075),
          # panel.grid.minor.x = element_line(linewidth = 0.025),
          strip.placement = "out",
          strip.background = element_blank(),
          strip.text =  element_text(angle = 0,size=4),
          plot.margin = unit(c(0,0,0,0),"pt"),
          line=element_line(linewidth = 0.1),
          legend.position = "bottom",
          legend.box.margin=margin(-5,-5,-5,-5),
          # legend.justification="top",
          legend.text = element_text(angle = 90,vjust = 0.5,hjust = 0.5),
          plot.background =element_blank(),
          legend.key.size = unit(5,"pt")
    )
  print(p)
  
}

10 Session info

print(sessionInfo())
## R version 4.5.0 (2025-04-11)
## Platform: aarch64-apple-darwin20
## Running under: macOS Ventura 13.1
## 
## Matrix products: default
## BLAS:   /Library/Frameworks/R.framework/Versions/4.5-arm64/Resources/lib/libRblas.0.dylib 
## LAPACK: /Library/Frameworks/R.framework/Versions/4.5-arm64/Resources/lib/libRlapack.dylib;  LAPACK version 3.12.1
## 
## locale:
## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
## 
## time zone: Europe/Madrid
## tzcode source: internal
## 
## attached base packages:
##  [1] grid      parallel  stats4    stats     graphics  grDevices utils    
##  [8] datasets  methods   base     
## 
## other attached packages:
##  [1] MafH5.gnomAD.v4.0.GRCh38_3.19.0                   
##  [2] GenomicScores_2.20.2                              
##  [3] SNPlocs.Hsapiens.dbSNP155.GRCh38_0.99.24          
##  [4] BSgenome_1.76.0                                   
##  [5] rtracklayer_1.68.0                                
##  [6] BiocIO_1.18.0                                     
##  [7] circlize_0.4.16                                   
##  [8] ComplexHeatmap_2.24.1                             
##  [9] patchwork_1.3.2                                   
## [10] IlluminaHumanMethylation450kanno.ilmn12.hg19_0.6.1
## [11] minfi_1.54.1                                      
## [12] bumphunter_1.50.0                                 
## [13] locfit_1.5-9.12                                   
## [14] iterators_1.0.14                                  
## [15] foreach_1.5.2                                     
## [16] SummarizedExperiment_1.38.1                       
## [17] Biobase_2.68.0                                    
## [18] MatrixGenerics_1.20.0                             
## [19] matrixStats_1.5.0                                 
## [20] Biostrings_2.76.0                                 
## [21] XVector_0.48.0                                    
## [22] openxlsx_4.2.8                                    
## [23] GenomicRanges_1.60.0                              
## [24] GenomeInfoDb_1.44.2                               
## [25] IRanges_2.42.0                                    
## [26] S4Vectors_0.46.0                                  
## [27] BiocGenerics_0.54.0                               
## [28] generics_0.1.4                                    
## [29] pals_1.10                                         
## [30] ggpubr_0.6.1                                      
## [31] ggplot2_3.5.2                                     
## [32] dplyr_1.1.4                                       
## [33] janitor_2.2.1                                     
## [34] data.table_1.17.8                                 
## [35] BiocStyle_2.36.0                                  
## 
## loaded via a namespace (and not attached):
##   [1] splines_4.5.0                     filelock_1.0.3                   
##   [3] bitops_1.0-9                      tibble_3.3.0                     
##   [5] preprocessCore_1.70.0             XML_3.99-0.19                    
##   [7] lifecycle_1.0.4                   rstatix_0.7.2.999                
##   [9] fastcluster_1.3.0                 doParallel_1.0.17                
##  [11] lattice_0.22-7                    MASS_7.3-65                      
##  [13] base64_2.0.2                      scrime_1.3.5                     
##  [15] backports_1.5.0                   magrittr_2.0.3                   
##  [17] limma_3.64.3                      sass_0.4.10                      
##  [19] rmarkdown_2.29                    BSgenome.Hsapiens.UCSC.hg38_1.4.5
##  [21] jquerylib_0.1.4                   yaml_2.3.10                      
##  [23] doRNG_1.8.6.2                     zip_2.3.3                        
##  [25] askpass_1.2.1                     mapproj_1.2.12                   
##  [27] DBI_1.2.3                         RColorBrewer_1.1-3               
##  [29] lubridate_1.9.4                   maps_3.4.3                       
##  [31] abind_1.4-8                       quadprog_1.5-8                   
##  [33] purrr_1.1.0                       RCurl_1.98-1.17                  
##  [35] rappdirs_0.3.3                    GenomeInfoDbData_1.2.14          
##  [37] rentrez_1.2.4                     genefilter_1.90.0                
##  [39] annotate_1.86.1                   DelayedMatrixStats_1.30.0        
##  [41] codetools_0.2-20                  DelayedArray_0.34.1              
##  [43] xml2_1.4.0                        shape_1.4.6.1                    
##  [45] tidyselect_1.2.1                  UCSC.utils_1.4.0                 
##  [47] farver_2.1.2                      beanplot_1.3.1                   
##  [49] BiocFileCache_2.16.1              illuminaio_0.50.0                
##  [51] GenomicAlignments_1.44.0          jsonlite_2.0.0                   
##  [53] GetoptLong_1.0.5                  multtest_2.64.0                  
##  [55] Formula_1.2-5                     survival_3.8-3                   
##  [57] tools_4.5.0                       Rcpp_1.1.0                       
##  [59] glue_1.8.0                        SparseArray_1.8.1                
##  [61] xfun_0.53                         HDF5Array_1.36.0                 
##  [63] withr_3.0.2                       BiocManager_1.30.26              
##  [65] fastmap_1.2.0                     rhdf5filters_1.20.0              
##  [67] openssl_2.3.3                     digest_0.6.37                    
##  [69] timechange_0.3.0                  R6_2.6.1                         
##  [71] colorspace_2.1-1                  Cairo_1.6-5                      
##  [73] dichromat_2.0-0.1                 RSQLite_2.4.3                    
##  [75] h5mread_1.0.1                     utf8_1.2.6                       
##  [77] tidyr_1.3.1                       httr_1.4.7                       
##  [79] S4Arrays_1.8.1                    pkgconfig_2.0.3                  
##  [81] gtable_0.3.6                      blob_1.2.4                       
##  [83] siggenes_1.82.0                   htmltools_0.5.8.1                
##  [85] carData_3.0-5                     bookdown_0.44                    
##  [87] clue_0.3-66                       scales_1.4.0                     
##  [89] png_0.1-8                         snakecase_0.11.1                 
##  [91] knitr_1.50                        rstudioapi_0.17.1                
##  [93] reshape2_1.4.4                    tzdb_0.5.0                       
##  [95] rjson_0.2.23                      nlme_3.1-168                     
##  [97] curl_7.0.0                        GlobalOptions_0.1.2              
##  [99] cachem_1.1.0                      rhdf5_2.52.1                     
## [101] stringr_1.5.1                     BiocVersion_3.21.1               
## [103] AnnotationDbi_1.70.0              restfulr_0.0.16                  
## [105] GEOquery_2.76.0                   pillar_1.11.0                    
## [107] reshape_0.8.10                    vctrs_0.6.5                      
## [109] car_3.1-3                         dbplyr_2.5.0                     
## [111] cluster_2.1.8.1                   xtable_1.8-4                     
## [113] evaluate_1.0.5                    tinytex_0.57                     
## [115] magick_2.8.7                      readr_2.1.5                      
## [117] GenomicFeatures_1.60.0            cli_3.6.5                        
## [119] compiler_4.5.0                    Rsamtools_2.24.0                 
## [121] rlang_1.1.6                       crayon_1.5.3                     
## [123] rngtools_1.5.2                    ggsignif_0.6.4                   
## [125] labeling_0.4.3                    nor1mix_1.3-3                    
## [127] mclust_6.1.1                      plyr_1.8.9                       
## [129] stringi_1.8.7                     BiocParallel_1.42.1              
## [131] Matrix_1.7-4                      BSgenome.Hsapiens.UCSC.hg19_1.4.3
## [133] hms_1.1.3                         sparseMatrixStats_1.20.0         
## [135] bit64_4.6.0-1                     Rhdf5lib_1.30.0                  
## [137] KEGGREST_1.48.1                   statmod_1.5.0                    
## [139] AnnotationHub_3.16.1              broom_1.0.9                      
## [141] memoise_2.0.1                     bslib_0.9.0                      
## [143] bit_4.6.0