8  Combining and comparing multiple data modalities

Single molecule footprinting data itself may already provide more than a single data modality: While 6mA calls provide information about the accessiblity of sequenced molecules, additional base modifications such as 5mCpG and 5hmCpG inform about endogenous modification states. When working with data from diploid organisms, the sequence at heterozygous loci allows separate quantification of individual alleles (see ).

In the sections below we are illustrating the integration of the above data modalities (allele-specific accessibility and DNA methylation at CpG dinucleotides) with ChIP-seq data at heterozygous CTCF binding sites. This illustrates how the sequence variation that discriminates the two alleles affects the binding of CTCF, and consequently also the chromatin accessibility and DNA methylation of each allele.

8.1 Load data and packages

We start by loading the required packages, high-confidence heterozygous SNVs and preparing reference (REF) and alternative (ALT) version of the genome by injecting the SNVs into the genome assembly.

Show/hide code
# Packages
BSgenomeName <- "BSgenome.Mmusculus.GENCODE.GRCm39.gencodeM34"
library(footprintR)
library(ggplot2)
library(patchwork)
library(dplyr)
library(ggpubr)
library(GenomicRanges)
library(GenomicAlignments)
library(VariantAnnotation)
library(SummarizedExperiment)
library(BSgenomeName, character.only = TRUE)
library(JASPAR2024)
library(TFBSTools)
library(universalmotif)
library(forcats)
library(Hmisc)
library(parallel)
library(stringdist)
library(SparseArray)

# number of CPUs to use for parallel tasks
ncpu <- 24

# modBam files
bamfilesC <- c(WT_1 = "data/mESC_wt_5mCG_5hmCG_rep1.bam",
               WT_2 = "data/mESC_wt_5mCG_5hmCG_rep2.bam")
bamfilesA <- c(WT_1 = "data/mESC_wt_6mA_rep1.bam",
               WT_2 = "data/mESC_wt_6mA_rep2.bam")

# ChIP bam files
chipbam <- c(CTCF_1 = "data/mESC_wt_CTCF_ChIP_rep1.bam", # GSM747534
             CTCF_2 = "data/mESC_wt_CTCF_ChIP_rep2.bam", # GSM747535
             CTCF_3 = "data/mESC_wt_CTCF_ChIP_rep3.bam") # GSM747534

# Heterozygous SNVs
hetsnv <- readVcf("data/het_snp.vcf.gz")

# ... extract SNV positions and make sure they are not indels
hetpos <- as(rowRanges(hetsnv), "GPos")
stopifnot(all(width(hetpos$REF) == 1L))
stopifnot(all(lengths(hetpos$ALT) == 1L))
stopifnot(all(width(unlist(hetpos$ALT)) == 1L))
hetpos$ALT <- unlist(hetpos$ALT)

# Load genome
gnm <- get(BSgenomeName)

# ... create refernce and alternative genomes by injecting SNVs
gnmREF <- gnmALT <- getSeq(gnm)
for (chr in names(gnmREF)) {
    i <- which(seqnames(hetpos) == chr)
    gnmREF[[chr]] <- replaceLetterAt(x = gnmREF[[chr]],
                                     at = start(hetpos)[i],
                                     letter = unlist(hetpos$REF[i]),
                                     verbose = interactive())
    gnmALT[[chr]] <- replaceLetterAt(x = gnmALT[[chr]],
                                     at = start(hetpos)[i],
                                     letter = unlist(hetpos$ALT[i]),
                                     verbose = interactive())
}

8.2 Scan the genome with the CTCF motif and identify sites that overlap sequence variants

We next get the CTCF motif from the Jaspar database (Rauluseviciute et al. ()) and scan the genome for high scoring matches that overlap heterozygous SNVs.

We will scan both reference and alternative version of the genome and combine them afterwards, in order to not miss any high-scoring CTCF motif matches due to the presence of SNVs.

Show/hide code
# get CTCF motif from Jaspar
jaspar <- JASPAR2024()
dbfunc <- getFromNamespace(x = "db", ns = "JASPAR2024")
mdb <- RSQLite::dbConnect(RSQLite::SQLite(), dbfunc(jaspar))
tf_motif <- getMatrixByID(x = mdb, ID = "MA0139.2")
RSQLite::dbDisconnect(mdb)
seqLogo(toICM(tf_motif), xaxis = FALSE, yaxis = FALSE)
Figure 8.1
Show/hide code
# scan REF and ALT genomes for motif hits
hitsREF <- scan_sequences(motifs = tf_motif,
                          sequences = gnmREF,
                          threshold = 8e-5,
                          threshold.type = "pvalue",
                          RC = TRUE,
                          use.gaps = FALSE,
                          return.granges = TRUE,
                          nthreads = ncpu,
                          verbose = if(interactive()) 2 else 0)
hitsALT <- scan_sequences(motifs = tf_motif,
                          sequences = gnmALT,
                          threshold = 8e-5,
                          threshold.type = "pvalue",
                          RC = TRUE,
                          use.gaps = FALSE,
                          return.granges = TRUE,
                          nthreads = ncpu,
                          verbose = if(interactive()) 2 else 0)

# combine (remove overlapping hits on the same strand)
hits <- reduce(c(hitsREF, hitsALT))
hits <- hits[width(hits) == length(tf_motif)]

At this point, we have 539 thousand hits to the CTCF motif in the genome. We next select the sites that overlap any of our heterozygous SNVs.

Show/hide code
hits_het <- subsetByOverlaps(hits, hetpos, ignore.strand = TRUE)

# filter out sites with more than 4 overlapping SNVs
nSNVs <- countOverlaps(hits_het, hetpos, ignore.strand = TRUE)
table(nSNVs)
nSNVs
   1    2    3    4    5    6 
5136  651   96   25    4    2 
Show/hide code
hits_het <- hits_het[nSNVs <= 4]

Finally, we score the 5908 heterozygous hits to get a motif match score for both reference and alternative alleles. We get a symmetric distribution around zero with similar numbers of motifs that increase and decrease there match score in ALT compared to REF. Only few motifs change there score by more than 50% of the maximal score (22.6).

Show/hide code
# score hits
seqsREF <- getSeq(gnmREF, hits_het)
seqsALT <- getSeq(gnmALT, hits_het)

hits_het$scoreREF <- score_match(motif = tf_motif, match = as.character(seqsREF))
hits_het$scoreALT <- score_match(motif = tf_motif, match = as.character(seqsALT))
hits_het$scoreDelta <- hits_het$scoreREF - hits_het$scoreALT
hits_het$scoreDeltaPercent <- hits_het$scoreDelta / hitsREF$max.score[1] * 100
hits_het$scoreDeltaBinned <- Hmisc::cut2(
    x = hits_het$scoreDelta,
    cuts = c(min(hits_het$scoreDelta) - 0.1, -10, -5, -2, 2, 5, 10,
             max(hits_het$scoreDelta) + 0.1))
hits_het$scoreDeltaBinned <- fct_rev(hits_het$scoreDeltaBinned)

scoreDeltaBinnedCols <- structure(c("#611300", "#CC4E25", "#EBB0A8",
                                    "#CCCCCC", "#B3D0E4", "#008BBD",
                                    "#003560"),
                                  names = levels(hits_het$scoreDeltaBinned))

ggplot(as.data.frame(hits_het), aes(scoreDeltaPercent)) +
    stat_bin(bins = 20, geom = "col",
             aes(y = after_stat(count), fill = after_stat(x))) +
    scale_fill_gradient2(low = scoreDeltaBinnedCols[1],
                         mid = scoreDeltaBinnedCols[4],
                         high = scoreDeltaBinnedCols[7]) +
    geom_vline(xintercept = 0, linetype = "dashed") +
    geom_vline(xintercept = c(-50, 50), linetype = "dotted") +
    coord_cartesian(xlim = c(-100, 100)) +
    labs(x = "Change of motif score (% of maximal score, REF - ALT)",
         y = "Number of CTCF motif hits",
         fill = "Change of\nmotif score") +
    theme_bw() +
    theme(legend.position = "inside",
          legend.position.inside = c(.02, .98),
          legend.justification = c(0, 1))
Figure 8.2

8.3 Annotate heterozygous CTCF sites

We next annotate our CTCF sites with experimental measurements. To account for the limited resolution and exploit the autocorrelation of our experimental data, we will include the data in a small window of 180bp around each CTCF site. Furthermore, we will run the calculations in parallel over the sites using mclapply from the parallel package. This step is nevertheless slow and takes about ~13 seconds per site and CPU on our system.

All measurements will be calculated separately for each allele. For single molecule footprinting data, we do this by grouping the reads based on overlapping SNVs, as outlined in . For the ChIP-seq data, we load the read sequences using stackStringsFromBam from the GenomicAlignments package and separate them by allele based on overlapping SNVs. The CTCF ChIP samples correspond to the samples GSM747534, GSM747535 and GSM747536 from Stadler et al. ().

Show/hide code
# expand sites to 180 bp windows centered on motif mid
hits_hetExt <- resize(hits_het, width = 180, fix = "center")

# iterate over sites and combine individual results
pd <- do.call(rbind, mclapply(seq_along(hits_hetExt), function(i) {
    # allocate empty result
    hetpos1 <- subsetByOverlaps(x = hetpos, ranges = hits_hetExt[i])
    seqREF <- paste(as.character(hetpos1$REF), collapse = "")
    seqALT <- paste(as.character(hetpos1$ALT), collapse = "")
    seq1 <- getSeq(gnm, hits_hetExt[i])
    res <- data.frame(locus = as.character(hits_hetExt[i]),
                      nA = countPattern("A", seq1[[1]], fixed = TRUE),
                      nCpG = countPattern("CG", seq1[[1]], fixed = TRUE),
                      motifScoreREF = hits_hetExt$scoreREF[i],
                      motifScoreALT = hits_hetExt$scoreALT[i],
                      motifScoreDelta = hits_hetExt$scoreDelta[i],
                      motifScoreDeltaBinned = hits_het$scoreDeltaBinned[i],
                      varlabelREF = seqREF,
                      varlabelALT = seqALT,
                      CpGmethNumReadsREF = 0,
                      CpGmethNumReadsALT = 0,
                      CpGmethNumReadsNA = 0,
                      CpGfracmodREF = NA,
                      CpGfracmodALT = NA,
                      CpGfracmodDelta = NA,
                      AmethNumReadsREF = 0,
                      AmethNumReadsALT = 0,
                      AmethNumReadsNA = 0,
                      AfracmodREF = NA,
                      AfracmodALT = NA,
                      AfracmodDelta = NA,
                      chipNumReadsREF = 0,
                      chipNumReadsALT = 0,
                      chipNumReadsNA = 0,
                      chipLog2FC = 0
    )
    
    # load read-level data
    # ... 5mCpG
    if (res[1, "nCpG"] > 0) {
        seC <- readModBam(bamfiles = bamfilesC,
                          regions = hits_hetExt[i],
                          modbase = "m", level = "read",
                          sequenceContextWidth = 3, sequenceReference = gnmREF,
                          variantPositions = hetpos1, 
                          trim = TRUE, BPPARAM = BiocParallel::SerialParam(),
                          verbose = interactive())
        if (nrow(seC) > 0) {
            # ... filter out non-CpGs (in any genome)
            seC <- filterPositions(seC, filters = "sequenceContext",
                                   sequenceContext = "NCG", assayNameNA = "mod_prob")
            if (nrow(seC) > 0) {
                seC <- addSeqContext(x = seC, sequenceContextWidth = 3,
                                     sequenceReference = gnmALT)
                seC <- filterPositions(seC, filters = "sequenceContext",
                                       sequenceContext = "NCG", assayNameNA = "mod_prob")
                if (nrow(seC) > 0) {
                    # cluster by allele
                    varlabels <- structure(
                        unlist(lapply(seC$readInfo, "[[", "variant_label"), use.names = FALSE),
                        names = unlist(lapply(seC$readInfo, rownames), use.names = FALSE))
                    dists <- stringdistmatrix(a = c(seqREF, seqALT),
                                              b = varlabels, method = "hamming",
                                              nthread = 2) / nchar(varlabels[1])
                    methGroup <- ifelse(colMins(dists) < 0.34,
                                        c("REF", "ALT")[apply(dists, 2, which.min)], NA)
                    # calculate average modification fraction
                    modprob <- as.matrix(assay(seC, "mod_prob"))
                    percmeth <- lapply(split(names(varlabels), methGroup), function(rid) {
                        nmod <- sum(nnavals(modprob[, rid]) >= 0.5)
                        nvalid <- sum(is_nonna(modprob)[, rid])
                        nmod / nvalid
                    })
                    
                    # add to `res`
                    res[1, c("CpGmethNumReadsREF", "CpGmethNumReadsALT", "CpGmethNumReadsNA",
                             "CpGfracmodREF", "CpGfracmodALT", "CpGfracmodDelta")] <- c(
                                 CpGmethNumReadsREF = sum(methGroup == "REF", na.rm = TRUE),
                                 CpGmethNumReadsALT = sum(methGroup == "ALT", na.rm = TRUE),
                                 CpGmethNumReadsNA = sum(is.na(methGroup)),
                                 CpGfracmodREF = percmeth$REF %||% NA,
                                 CpGfracmodALT = percmeth$ALT %||% NA,
                                 CpGfracmodDelta = (percmeth$REF %||% NA) - (percmeth$ALT %||% NA))
                }
            }
        }
    }
    
    # ... 6mA
    if (res[1, "nA"] > 0) {
        seA <- readModBam(bamfiles = bamfilesA,
                          regions = hits_hetExt[i],
                          modbase = "a", level = "read",
                          sequenceContextWidth = 1, sequenceReference = gnmREF,
                          variantPositions = hetpos1, 
                          trim = TRUE, BPPARAM = BiocParallel::SerialParam(),
                          verbose = interactive())
        if (nrow(seA) > 0) {
            # ... filter out non-As (in any genome)
            seA <- filterPositions(seA, filters = "sequenceContext",
                                   sequenceContext = "A", assayNameNA = "mod_prob")
            if (nrow(seA) > 0) {
                seA <- addSeqContext(x = seA, sequenceContextWidth = 1,
                                     sequenceReference = gnmALT)
                seA <- filterPositions(seA, filters = "sequenceContext",
                                       sequenceContext = "A", assayNameNA = "mod_prob")
                if (nrow(seA) > 0) {
                    # cluster by allele
                    varlabels <- structure(
                        unlist(lapply(seA$readInfo, "[[", "variant_label"), use.names = FALSE),
                        names = unlist(lapply(seA$readInfo, rownames), use.names = FALSE))
                    dists <- stringdistmatrix(a = c(seqREF, seqALT),
                                              b = varlabels, method = "hamming",
                                              nthread = 2) / nchar(varlabels[1])
                    methGroup <- ifelse(colMins(dists) < 0.34,
                                        c("REF", "ALT")[apply(dists, 2, which.min)], NA)
                    
                    # calculate average modification fraction
                    modprob <- as.matrix(assay(seA, "mod_prob"))
                    percmeth <- lapply(split(names(varlabels), methGroup), function(rid) {
                        nmod <- sum(nnavals(modprob[, rid]) >= 0.5)
                        nvalid <- sum(is_nonna(modprob)[, rid])
                        nmod / nvalid
                    })

                    # add to `res`
                    res[1, c("AmethNumReadsREF", "AmethNumReadsALT", "AmethNumReadsNA",
                             "AfracmodREF", "AfracmodALT", "AfracmodDelta")] <- c(
                                 AmethNumReadsREF = sum(methGroup == "REF", na.rm = TRUE),
                                 AmethNumReadsALT = sum(methGroup == "ALT", na.rm = TRUE),
                                 AmethNumReadsNA = sum(is.na(methGroup)),
                                 AfracmodREF = percmeth$REF %||% NA,
                                 AfracmodALT = percmeth$ALT %||% NA,
                                 AfracmodDelta = (percmeth$REF %||% NA) - (percmeth$ALT %||% NA))
                }
            }
        }
    }
        
    # ... CTCF ChIP-seq
    reads <- do.call(c, unname(lapply(chipbam, function(bam1) {
        stackStringsFromBam(file = bam1, param = unstrand(hits_hetExt[i]), what = "seq")
    })))
    
    if (length(reads) > 0) {
        varlabels <- apply(do.call(cbind, lapply(start(hetpos1) - start(hits_hetExt[i]) + 1, function(pos) {
            as.character(subseq(x = reads, start = pos, width = 1))
        })), 1, paste, collapse = "")
        dists <- stringdistmatrix(a = c(seqREF, seqALT),
                                  b = varlabels, method = "hamming",
                                  nthread = 2)
        chipGroup <- ifelse(dists[1,] < dists[2,], "REF",
                            ifelse(dists[2,] < dists[1,], "ALT", NA))
    } else {
        chipGroup <- character(0)
    }
    # add to `res`
    res[1, c("chipNumReadsREF", "chipNumReadsALT",
             "chipNumReadsNA", "chipLog2FC")] <- c(
                 chipNumReadsREF = sum(chipGroup == "REF", na.rm = TRUE),
                 chipNumReadsALT = sum(chipGroup == "ALT", na.rm = TRUE),
                 chipNumReadsNA = sum(is.na(chipGroup)),
                 chipLog2FC = log2((sum(chipGroup == "REF", na.rm = TRUE) + 16) /
                                       (sum(chipGroup == "ALT", na.rm = TRUE) + 16)))
    
    return(res)
}, mc.cores = ncpu, mc.preschedule = FALSE))

8.4 Visualize differences between alleles at each heterozygous CTCF site

We know that the binding of a transcription factor leads to an increase of local chromatin accessibility, as well as a decrease in local DNA methylation. We thus expect to find clear associations between the allelic changes of these two and CTCF ChIP signals, and also with changes of motif scores that are the underlying cause of allelic differences.

8.4.1 CTCF binding (ChIP) versus accessibility (6mA)

Show/hide code
pdsel <- pd |> filter(CpGmethNumReadsREF > 1,
                      CpGmethNumReadsALT > 1,
                      chipNumReadsREF + chipNumReadsALT > 5)

ggplot(pdsel, mapping = aes(chipLog2FC, AfracmodDelta)) +
    geom_point(aes(colour = motifScoreDeltaBinned)) +
    scale_colour_manual(values =  scoreDeltaBinnedCols) +
    stat_cor(label.x.npc = "left") +
    labs(title = paste0("Predicted CTCF sites overlapping heterozygous SNVs (n=", nrow(pdsel), ")"),
         x = "Change of CTCF binding (log2 ref/alt)",
         y = "Change of accessibility (fraction 6mA, ref - alt)",
         colour = "Change of motif\nscore (ref - alt)") +
    theme_bw() +
    theme(legend.position = "inside",
          legend.position.inside = c(0.98, 0.02),
          legend.justification = c(1, 0))
Figure 8.3

8.5 CTCF binding (ChIP) versus DNA methylation (5mCpG)

Show/hide code
pdsel <- pd |> filter(CpGmethNumReadsREF > 1,
                      CpGmethNumReadsALT > 1,
                      chipNumReadsREF + chipNumReadsALT > 5)

ggplot(pdsel, mapping = aes(chipLog2FC, CpGfracmodDelta)) +
    geom_point(aes(colour = motifScoreDeltaBinned)) +
    scale_colour_manual(values = scoreDeltaBinnedCols) +
    ggpubr::stat_cor(label.x.npc = "right", hjust = 1) +
    labs(title = paste0("Predicted CTCF sites overlapping heterozygous SNVs (n=", nrow(pdsel), ")"),
         x = "Change of CTCF binding (log2 ref/alt)",
         y = "Change of 5mCpG (ref - alt)",
         colour = "Change of motif\nscore (ref - alt)") +
    theme_bw() +
    theme(legend.position = "inside",
          legend.position.inside = c(0.02, 0.02),
          legend.justification = c(0, 0))
Figure 8.4

8.6 Session info

Click to view session info
Show/hide code
sessioninfo::session_info(info = "packages")
═ Session info ═══════════════════════════════════════════════════════════════
─ Packages ───────────────────────────────────────────────────────────────────
 package                                      * version   date (UTC) lib source
 abind                                        * 1.4-8     2024-09-12 [1] CRAN (R 4.5.0)
 AnnotationDbi                                  1.70.0    2025-04-15 [1] Bioconductor 3.21 (R 4.5.0)
 backports                                      1.5.0     2024-05-23 [1] CRAN (R 4.5.0)
 base64enc                                      0.1-3     2015-07-28 [1] CRAN (R 4.5.0)
 Biobase                                      * 2.68.0    2025-04-15 [1] Bioconductor 3.21 (R 4.5.0)
 BiocFileCache                                * 2.16.0    2025-04-15 [1] Bioconductor 3.21 (R 4.5.0)
 BiocGenerics                                 * 0.54.0    2025-04-15 [1] Bioconductor 3.21 (R 4.5.0)
 BiocIO                                       * 1.18.0    2025-04-15 [1] Bioconductor 3.21 (R 4.5.0)
 BiocParallel                                   1.42.1    2025-06-01 [1] Bioconductor 3.21 (R 4.5.0)
 Biostrings                                   * 2.76.0    2025-04-15 [1] Bioconductor 3.21 (R 4.5.0)
 bit                                            4.6.0     2025-03-06 [1] CRAN (R 4.5.0)
 bit64                                          4.6.0-1   2025-01-16 [1] CRAN (R 4.5.0)
 bitops                                         1.0-9     2024-10-03 [1] CRAN (R 4.5.0)
 blob                                           1.2.4     2023-03-17 [1] CRAN (R 4.5.0)
 broom                                          1.0.8     2025-03-28 [1] CRAN (R 4.5.0)
 BSgenome                                     * 1.76.0    2025-04-15 [1] Bioconductor 3.21 (R 4.5.0)
 BSgenome.Mmusculus.GENCODE.GRCm39.gencodeM34 * 0.1.0     2025-04-17 [1] Bioconductor
 cachem                                         1.1.0     2024-05-16 [1] CRAN (R 4.5.0)
 car                                            3.1-3     2024-09-27 [1] CRAN (R 4.5.0)
 carData                                        3.0-5     2022-01-06 [1] CRAN (R 4.5.0)
 caTools                                        1.18.3    2024-09-04 [1] CRAN (R 4.5.0)
 checkmate                                      2.3.2     2024-07-29 [1] CRAN (R 4.5.0)
 cli                                            3.6.5     2025-04-23 [1] CRAN (R 4.5.0)
 cluster                                        2.1.8.1   2025-03-12 [2] CRAN (R 4.5.0)
 codetools                                      0.2-20    2024-03-31 [2] CRAN (R 4.5.0)
 colorspace                                     2.1-1     2024-07-26 [1] CRAN (R 4.5.0)
 crayon                                         1.5.3     2024-06-20 [1] CRAN (R 4.5.0)
 curl                                           6.3.0     2025-06-06 [1] CRAN (R 4.5.0)
 data.table                                     1.17.4    2025-05-26 [1] CRAN (R 4.5.0)
 DBI                                            1.2.3     2024-06-02 [1] CRAN (R 4.5.0)
 dbplyr                                       * 2.5.0     2024-03-19 [1] CRAN (R 4.5.0)
 DelayedArray                                   0.34.1    2025-04-17 [1] Bioconductor 3.21 (R 4.5.0)
 dichromat                                      2.0-0.1   2022-05-02 [1] CRAN (R 4.5.0)
 digest                                         0.6.37    2024-08-19 [1] CRAN (R 4.5.0)
 DirichletMultinomial                           1.50.0    2025-04-15 [1] Bioconductor 3.21 (R 4.5.0)
 dplyr                                        * 1.1.4     2023-11-17 [1] CRAN (R 4.5.0)
 evaluate                                       1.0.3     2025-01-10 [1] CRAN (R 4.5.0)
 farver                                         2.1.2     2024-05-13 [1] CRAN (R 4.5.0)
 fastmap                                        1.2.0     2024-05-15 [1] CRAN (R 4.5.0)
 filelock                                       1.0.3     2023-12-11 [1] CRAN (R 4.5.0)
 footprintR                                   * 0.3.5     2025-06-04 [1] Github (fmicompbio/footprintR@612f713)
 forcats                                      * 1.0.0     2023-01-29 [1] CRAN (R 4.5.0)
 foreign                                        0.8-90    2025-03-31 [2] CRAN (R 4.5.0)
 Formula                                        1.2-5     2023-02-24 [1] CRAN (R 4.5.0)
 generics                                     * 0.1.4     2025-05-09 [1] CRAN (R 4.5.0)
 GenomeInfoDb                                 * 1.44.0    2025-04-15 [1] Bioconductor 3.21 (R 4.5.0)
 GenomeInfoDbData                               1.2.14    2025-04-17 [1] Bioconductor
 GenomicAlignments                            * 1.44.0    2025-04-15 [1] Bioconductor 3.21 (R 4.5.0)
 GenomicFeatures                                1.60.0    2025-04-15 [1] Bioconductor 3.21 (R 4.5.0)
 GenomicRanges                                * 1.60.0    2025-04-15 [1] Bioconductor 3.21 (R 4.5.0)
 ggforce                                        0.4.2     2024-02-19 [1] CRAN (R 4.5.0)
 ggplot2                                      * 3.5.2     2025-04-09 [1] CRAN (R 4.5.0)
 ggpubr                                       * 0.6.0     2023-02-10 [1] CRAN (R 4.5.0)
 ggsignif                                       0.6.4     2022-10-13 [1] CRAN (R 4.5.0)
 glue                                           1.8.0     2024-09-30 [1] CRAN (R 4.5.0)
 gridExtra                                      2.3       2017-09-09 [1] CRAN (R 4.5.0)
 gtable                                         0.3.6     2024-10-25 [1] CRAN (R 4.5.0)
 gtools                                         3.9.5     2023-11-20 [1] CRAN (R 4.5.0)
 Hmisc                                        * 5.2-3     2025-03-16 [1] CRAN (R 4.5.0)
 htmlTable                                      2.4.3     2024-07-21 [1] CRAN (R 4.5.0)
 htmltools                                      0.5.8.1   2024-04-04 [1] CRAN (R 4.5.0)
 htmlwidgets                                    1.6.4     2023-12-06 [1] CRAN (R 4.5.0)
 httr                                           1.4.7     2023-08-15 [1] CRAN (R 4.5.0)
 IRanges                                      * 2.42.0    2025-04-15 [1] Bioconductor 3.21 (R 4.5.0)
 JASPAR2024                                   * 0.99.7    2024-11-13 [1] Bioconductor 3.21 (R 4.5.0)
 jsonlite                                       2.0.0     2025-03-27 [1] CRAN (R 4.5.0)
 KEGGREST                                       1.48.0    2025-04-15 [1] Bioconductor 3.21 (R 4.5.0)
 knitr                                          1.50      2025-03-16 [1] CRAN (R 4.5.0)
 labeling                                       0.4.3     2023-08-29 [1] CRAN (R 4.5.0)
 lattice                                        0.22-7    2025-04-02 [1] CRAN (R 4.5.0)
 lifecycle                                      1.0.4     2023-11-07 [1] CRAN (R 4.5.0)
 magrittr                                       2.0.3     2022-03-30 [1] CRAN (R 4.5.0)
 MASS                                           7.3-65    2025-02-28 [2] CRAN (R 4.5.0)
 Matrix                                       * 1.7-3     2025-03-11 [2] CRAN (R 4.5.0)
 MatrixGenerics                               * 1.20.0    2025-04-15 [1] Bioconductor 3.21 (R 4.5.0)
 matrixStats                                  * 1.5.0     2025-01-07 [1] CRAN (R 4.5.0)
 memoise                                        2.0.1     2021-11-26 [1] CRAN (R 4.5.0)
 nnet                                           7.3-20    2025-01-01 [2] CRAN (R 4.5.0)
 patchwork                                    * 1.3.0     2024-09-16 [1] CRAN (R 4.5.0)
 pillar                                         1.10.2    2025-04-05 [1] CRAN (R 4.5.0)
 pkgconfig                                      2.0.3     2019-09-22 [1] CRAN (R 4.5.0)
 png                                            0.1-8     2022-11-29 [1] CRAN (R 4.5.0)
 polyclip                                       1.10-7    2024-07-23 [1] CRAN (R 4.5.0)
 purrr                                          1.0.4     2025-02-05 [1] CRAN (R 4.5.0)
 pwalign                                        1.4.0     2025-04-15 [1] Bioconductor 3.21 (R 4.5.0)
 R6                                             2.6.1     2025-02-15 [1] CRAN (R 4.5.0)
 RColorBrewer                                   1.1-3     2022-04-03 [1] CRAN (R 4.5.0)
 Rcpp                                           1.0.14    2025-01-12 [1] CRAN (R 4.5.0)
 RCurl                                          1.98-1.17 2025-03-22 [1] CRAN (R 4.5.0)
 restfulr                                       0.0.15    2022-06-16 [1] CRAN (R 4.5.0)
 rjson                                          0.2.23    2024-09-16 [1] CRAN (R 4.5.0)
 rlang                                          1.1.6     2025-04-11 [1] CRAN (R 4.5.0)
 rmarkdown                                      2.29      2024-11-04 [1] CRAN (R 4.5.0)
 rpart                                          4.1.24    2025-01-07 [2] CRAN (R 4.5.0)
 Rsamtools                                    * 2.24.0    2025-04-15 [1] Bioconductor 3.21 (R 4.5.0)
 RSQLite                                        2.4.1     2025-06-08 [1] CRAN (R 4.5.0)
 rstatix                                        0.7.2     2023-02-01 [1] CRAN (R 4.5.0)
 rstudioapi                                     0.17.1    2024-10-22 [1] CRAN (R 4.5.0)
 rtracklayer                                  * 1.68.0    2025-04-15 [1] Bioconductor 3.21 (R 4.5.0)
 S4Arrays                                     * 1.8.1     2025-06-01 [1] Bioconductor 3.21 (R 4.5.0)
 S4Vectors                                    * 0.46.0    2025-04-15 [1] Bioconductor 3.21 (R 4.5.0)
 scales                                         1.4.0     2025-04-24 [1] CRAN (R 4.5.0)
 seqLogo                                        1.74.0    2025-04-15 [1] Bioconductor 3.21 (R 4.5.0)
 sessioninfo                                    1.2.3     2025-02-05 [1] CRAN (R 4.5.0)
 SparseArray                                  * 1.8.0     2025-04-15 [1] Bioconductor 3.21 (R 4.5.0)
 stringdist                                   * 0.9.15    2025-01-10 [1] CRAN (R 4.5.0)
 stringi                                        1.8.7     2025-03-27 [1] CRAN (R 4.5.0)
 stringr                                        1.5.1     2023-11-14 [1] CRAN (R 4.5.0)
 SummarizedExperiment                         * 1.38.1    2025-04-30 [1] Bioconductor 3.21 (R 4.5.0)
 TFBSTools                                    * 1.46.0    2025-04-15 [1] Bioconductor 3.21 (R 4.5.0)
 TFMPvalue                                      0.0.9     2022-10-21 [1] CRAN (R 4.5.0)
 tibble                                         3.3.0     2025-06-08 [1] CRAN (R 4.5.0)
 tidyr                                          1.3.1     2024-01-24 [1] CRAN (R 4.5.0)
 tidyselect                                     1.2.1     2024-03-11 [1] CRAN (R 4.5.0)
 tweenr                                         2.0.3     2024-02-26 [1] CRAN (R 4.5.0)
 UCSC.utils                                     1.4.0     2025-04-15 [1] Bioconductor 3.21 (R 4.5.0)
 universalmotif                               * 1.26.2    2025-04-23 [1] Bioconductor 3.21 (R 4.5.0)
 VariantAnnotation                            * 1.54.1    2025-05-11 [1] Bioconductor 3.21 (R 4.5.0)
 vctrs                                          0.6.5     2023-12-01 [1] CRAN (R 4.5.0)
 withr                                          3.0.2     2024-10-28 [1] CRAN (R 4.5.0)
 xfun                                           0.52      2025-04-02 [1] CRAN (R 4.5.0)
 XML                                            3.99-0.18 2025-01-01 [1] CRAN (R 4.5.0)
 XVector                                      * 0.48.0    2025-04-15 [1] Bioconductor 3.21 (R 4.5.0)
 yaml                                           2.3.10    2024-07-26 [1] CRAN (R 4.5.0)
 zoo                                            1.8-14    2025-04-10 [1] CRAN (R 4.5.0)

 [1] /tungstenfs/groups/gbioinfo/Appz/R/BioC/R-4.5-release-foss-2024.05_BioC-3.21-release-foss-2024.05
 [2] /tachyon/groups/gbioinfo/Appz/easybuild/software/R/4.5.0-foss-2024.05/lib64/R/library
 * ── Packages attached to the search path.

──────────────────────────────────────────────────────────────────────────────