Introduction

The chromatin interactions is involved in precise quantitative and spatiotemporal control of gene expression. The development of high-throughput experimental techniques, such as HiC-seq, HiCAR-seq, and InTAC-seq, for analyzing both the higher-order structure of chromatin and the interactions between protein and their nearby and remote regulatory elements has been developed to reveal how gene expression is controlled in genome-wide. The geomeTriD package enables users to visualize epigenomic data in both 2D and 3D.

Installation

if (!require("BiocManager", quietly = TRUE)) {
  install.packages("BiocManager")
}

BiocManager::install("geomeTriD")

Quick start

There are three major steps to view the epigenomic data by geomeTriD in 3D.

  1. Load data in the GRanges object with metadata of positions.

  2. Parse the data into a list of threeJsGeometry objects.

  3. View the data by threeJsViewer function by threeJs. .

library(geomeTriD)
## load data
obj <- readRDS(system.file("extdata", "4DNFI1UEG1HD.chr21.FLAMINGO.res.rds",
  package = "geomeTriD"
))
head(obj, n = 2)
## GRanges object with 2 ranges and 3 metadata columns:
##       seqnames            ranges strand |           x            y           z
##          <Rle>         <IRanges>  <Rle> |   <numeric>    <numeric>   <numeric>
##   [1]    chr21 31370001-31375000      * | 6.33426e-06 -8.63705e-06 3.89647e-06
##   [2]    chr21 31375001-31380000      * | 2.82577e-06 -4.26812e-06 1.95232e-06
##   -------
##   seqinfo: 1 sequence from an unspecified genome; no seqlengths
feature.gr <- readRDS(system.file("extdata", "4DNFI1UEG1HD.feature.gr.rds",
  package = "geomeTriD"
))
head(feature.gr, n = 2)
## GRanges object with 2 ranges and 4 metadata columns:
##             seqnames            ranges strand |     gene_id       label
##                <Rle>         <IRanges>  <Rle> | <character> <character>
##   100506215    chr21 32728097-32746781      + |   100506215  PAXBP1-AS1
##   100551499    chr21 32080316-32197813      - |   100551499   LINC00159
##                   col        type
##             <integer> <character>
##   100506215         3        gene
##   100551499         5        gene
##   -------
##   seqinfo: 711 sequences (1 circular) from hg38 genome
## create threeJsGeometry objects
list3d <- view3dStructure(obj,
  feature.gr = feature.gr,
  renderer = "none"
)
## plot the data
threeJsViewer(list3d)

if you have trouble in seeing the results, such as Firefox snap installation issue, please try to save it as a file and open it in an explorer.

widget <- threeJsViewer(list3d)
tmpdir <- 'path/to/a/folder'
dir.create(tmpdir, recursive = TRUE)
tmp <- tempfile(tmpdir = tmpdir, fileext = '.html')
htmlwidgets::saveWidget(widget, file=tmp)
utils::browseURL(tmp)

Prepare the inputs

The genomic contact frequency, eg output from HiC, can be converted into spatial distances and then visualized using optimization-based (such as manifold learning techniques) or probabilistic approaches (such as Markov Chain Monte Carlo). Available tools include, but not limited to, ShRec3D, GEM-FISH, Hierarchical3DGenome, RPR, SuperRec, ShNeigh, PASTIS, and FLAMINGO.

Above example are data generated by FLAMINGOrLite from the chromosome 21 of the HiC contact matrix of human GM12878 cells downloaded from 4DN.

In this package, a simple method to calculate the spatial positions from bin-based contact matrix by multi-dimensional scaling (MDS) algorithm is provided.

Generate the 3D coordinates from contact matrix

The data in .hic or .cool can be imported into GInteractions objects by trackViewer::importGInteractions function. Here we show how to generate the 3D coordinates using the mdsPlot function from the bin-based contact matrix by Kruskal’s Non-metric Multidimensional Scaling.

library(trackViewer)
library(InteractionSet)
# load the interaction data.
# to import your own data, please refer trackViewer help documents
gi_nij <- readRDS(system.file("extdata", "nij.chr6.51120000.53200000.gi.rds",
  package = "geomeTriD"
))
# the data is a GInteractions object with metadata score
head(gi_nij, n = 2)
## GInteractions object with 2 interactions and 1 metadata column:
##       seqnames1           ranges1     seqnames2           ranges2 |     score
##           <Rle>         <IRanges>         <Rle>         <IRanges> | <numeric>
##   [1]      chr6 51120000-51160000 ---      chr6 51120000-51160000 |   45.1227
##   [2]      chr6 51120000-51160000 ---      chr6 51160000-51200000 |   35.0006
##   -------
##   regions: 53 ranges and 0 metadata columns
##   seqinfo: 1 sequence from an unspecified genome; no seqlengths
# define a range to plot
range_chr6 <- GRanges("chr6", IRanges(51120000, 53200000))
# plot it if interactive
if (interactive()) { ## not run to reduce the package size.
  mdsPlot(gi_nij, range = range_chr6, k = 3, render = "threejs")
}

Add gene informations

Here we show how to add gene information along the strand.

# create gene annotations
library(TxDb.Hsapiens.UCSC.hg19.knownGene)
library(org.Hs.eg.db)
## get all genes
feature.gr <- genes(TxDb.Hsapiens.UCSC.hg19.knownGene)
## subset the data by target viewer region
feature.gr <- subsetByOverlaps(feature.gr, range(regions(gi_nij)))
## assign symbols for each gene
symbols <- mget(feature.gr$gene_id, org.Hs.egSYMBOL, ifnotfound = NA)
feature.gr$label[lengths(symbols) == 1] <- 
  unlist(symbols[lengths(symbols) == 1])
## assign colors for each gene
feature.gr$col <- sample(1:7, length(feature.gr), replace = TRUE)
## Here we replaced the some gene feature as cis-regulatory elements
## to validate how it will be treated by the plot
feature.gr$type <- sample(c("cRE", "gene"),
  length(feature.gr),
  replace = TRUE,
  prob = c(0.1, 0.9)
)
## set the size the cRE in the plot
feature.gr$pch <- rep(NA, length(feature.gr))
feature.gr$pch[feature.gr$type == "cRE"] <- 0.5
## features header
head(feature.gr, n = 2)
## GRanges object with 2 ranges and 5 metadata columns:
##             seqnames            ranges strand |     gene_id       label
##                <Rle>         <IRanges>  <Rle> | <character> <character>
##   100847075     chr6 53141791-53141869      + |   100847075     MIR5685
##      112744     chr6 52101484-52109298      - |      112744       IL17F
##                   col        type       pch
##             <integer> <character> <numeric>
##   100847075         2        gene        NA
##      112744         4        gene        NA
##   -------
##   seqinfo: 93 sequences (1 circular) from hg19 genome
# plot it if interactive
if (interactive()) { ## not run to reduce the package size.
  mdsPlot(gi_nij,
    range = range_chr6, feature.gr = feature.gr,
    k = 3, render = "threejs"
  )
}

Add additional signals along the strand

Here we show how to add CTCF ATAC-seq signals along the strand.

# one layer of signals. It is a `track` object
ctcf <- readRDS(system.file("extdata", "ctcf.sample.rds",
  package = "trackViewer"
))
# plot it if interactive
if (interactive()) { ## not run to reduce the package size.
  mdsPlot(gi_nij,
    range = range_chr6, feature.gr = feature.gr,
    genomicSigs = ctcf,
    ## we reverse the ATAC-seq signale to show where is open
    reverseGenomicSigs = TRUE,
    k = 3, render = "threejs"
  )
}

Add more signals such as ChIP-seq.

# create a random signal for demonstration
set.seed(1)
randomSig <- ctcf$dat
randomSig <- randomSig[sort(sample(seq_along(randomSig), 50))]
randomSig$score <- randomSig$score * 2 * runif(50)
head(randomSig, n = 2)
## GRanges object with 2 ranges and 1 metadata column:
##       seqnames            ranges strand |     score
##          <Rle>         <IRanges>  <Rle> | <numeric>
##   [1]     chr6 51188134-51188334      * |  0.779979
##   [2]     chr6 51267112-51270512      * |  1.554641
##   -------
##   seqinfo: 22 sequences from an unspecified genome
objs <- mdsPlot(gi_nij,
  range = range_chr6, feature.gr = feature.gr,
  genomicSigs = list(ctcf = ctcf, test = randomSig),
  reverseGenomicSigs = c(TRUE, FALSE),
  k = 3, render = "none"
)
## initial  value 46.625959 
## iter   5 value 18.494050
## iter  10 value 14.996469
## iter  15 value 11.509102
## iter  20 value 9.159639
## iter  25 value 8.392723
## iter  30 value 8.060898
## iter  35 value 7.956958
## final  value 7.939262 
## converged
threeJsViewer(objs)

view the data by rgl

## not run to reduce the package size.
library(rgl)
library(manipulateWidget)
rgl::clear3d() # Remove the earlier display
rglViewer(objs, background = "white")
rgl::rglwidget() %>%
  rgl::toggleWidget(tags = "tick_minor") %>%
  toggleWidget(tags = "tick_major") %>%
  toggleWidget(tags = "tick_labels") %>%
  toggleWidget(tags = "ctcf") %>%
  toggleWidget(tags = "test") %>%
  toggleWidget(tags = "backbone") %>%
  toggleWidget(tags = "gene_body") %>%
  toggleWidget(tags = "tss_labels") %>%
  toggleWidget(tags = "gene_labels") %>%
  toggleWidget(tags = "cRE") %>%
  rgl::asRow(last = 10)

view the genomic interaction data

Here we will show how to add the interaction pairs into the 3d plot.

## get the backbone 3d positions,
## it will be used as a position reference for the interaction data.
xyz <- extractBackbonePositions(objs)
# make the example easy to see
gi.subset <- gi_nij[distance(first(gi_nij), second(gi_nij))>50000]
hic <- create3dGenomicSignals(
  gi.subset, 
  xyz,
  name='segment', # name prefix for the geometry
  tag='hic', # name for the layer in the scene
  color = c('green', 'darkred'),
  topN=3, # only plot the top 3 events ordered by the scores.
  lwd.maxGenomicSigs = 3,
  alpha=0.5
  )
hic2 <- create3dGenomicSignals(
  gi.subset,
  xyz,
  name='polygon', # name prefix for the geometry
  tag='hic', # name for the layer in the scene
  color = c('blue', 'darkred'),
  topN=seq(4, 10), # only plot the top 4-10 events ordered by the scores.
  type = 'polygon'
  )
width(regions(gi.subset)) <- 101#for high resolution input (such as reads pairs)
hic3 <- create3dGenomicSignals(
  gi.subset, 
  xyz,
  name='segment', # name prefix for the geometry
  tag='hic', # name for the layer in the scene
  color = rainbow(40),
  topN=length(gi.subset),
  lwd.maxGenomicSigs = 5,
  alpha = 0.1
)
# plot it if interactive
if (interactive()) { ## not run to reduce the package size.
  threeJsViewer(c(objs, hic, hic2, hic3))
}

Plot chromatin interactions data as loopBouquet or MDS plot

Plot the data in 3D using the mdsPlot function to generate the 3D coordinates. Alternatively, users can plot it in 2d. Please note that current 2d plot can only handle one genomic signals.

## not run to reduce the package size.
geomeTriD::mdsPlot(gi_nij, range = range_chr6, feature.gr = feature.gr, genomicSigs = ctcf)

Different from most of the available tools, loopBouquetPlot try to plot the loops with the 2D structure. The nodes indicate the region with interactions and the edges indicates the interactions. The size of the nodes are relative to the width of the region. The features could be the cRE or gene. The cRE are shown as points with symbol 11.

gi_chr2 <- readRDS(system.file("extdata", "gi.rds", package = "trackViewer"))
range_chr2 <- GRanges("chr2", IRanges(234300000, 235000000))
gene_hg19 <- suppressMessages(genes(TxDb.Hsapiens.UCSC.hg19.knownGene))
feature.gr_chr2 <- subsetByOverlaps(gene_hg19, range(regions(gi_chr2)))
feature.gr_chr2$col <- sample(2:7, length(feature.gr_chr2), replace = TRUE)
feature.gr_chr2$type <- sample(c("cRE", "gene"),
  length(feature.gr_chr2),
  replace = TRUE,
  prob = c(0.1, 0.9)
)
feature.gr_chr2$pch <- rep(NA, length(feature.gr_chr2))
feature.gr_chr2$pch[feature.gr_chr2$type == "cRE"] <- 11
symbol <- mget(feature.gr_chr2$gene_id, org.Hs.egSYMBOL, ifnotfound = NA)
symbol <- unlist(lapply(symbol, function(.ele) .ele[1]))
feature.gr_chr2$label <- symbol
geomeTriD::loopBouquetPlot(gi_chr2, range_chr2, feature.gr_chr2)

## filter the links to simulate the data with less interactions
keep <- distance(first(gi_nij), second(gi_nij)) > 5e5 & gi_nij$score > 35
gi_nij <- gi_nij[keep]
# narrow the width of anchors to enhance the plots
reg <- regions(gi_nij)
wr <- floor(width(reg) / 4)
start(reg) <- start(reg) + wr
end(reg) <- end(reg) - wr
regions(gi_nij) <- reg
feature.gr <- subsetByOverlaps(gene_hg19, range(regions(gi_nij)))
feature.gr$col <- sample(2:7, length(feature.gr), replace = TRUE)
feature.gr$type <- sample(c("cRE", "gene"),
  length(feature.gr),
  replace = TRUE,
  prob = c(0.1, 0.9)
)
symbol <- mget(feature.gr$gene_id, org.Hs.egSYMBOL, ifnotfound = NA)
symbol <- unlist(lapply(symbol, function(.ele) .ele[1]))
feature.gr$label <- symbol
feature.gr <- c(
  feature.gr[sample(seq_along(feature.gr), 5)],
  feature.gr[feature.gr$type == "cRE"][1]
)
feature.gr <- unique(sort(feature.gr))
geomeTriD::loopBouquetPlot(gi_nij, range_chr6, feature.gr,
  coor_tick_unit = 5e4,
  coor_mark_interval = 5e5,
  genomicSigs = ctcf
)

Plot single cells in 3d

geomeTriD can be used to view data in 3D. Here we will show how to use it to plot the single cell data in 3D. The input data should be a data.frame with x,y,z coordinates.

library(geomeTriD)
cells <- readRDS(system.file("extdata", "pbmc_small.3d.rds",
  package = "geomeTriD"
))
head(cells)
##                   umap_1     umap_2    umap_3 nCount_RNA nFeature_RNA
## ATGCCAGAACGACT -2.195171  0.6205683 1.1399260         70           47
## CATGGCCTGTGCAT -2.425737  0.3946877 1.5394660         85           52
## GAACCTGATGAACC -1.300247 -2.0641031 0.2079445         87           50
## TGACTGGATTCTCA -1.280686  2.2639842 1.0135704        127           56
## AGTCAGACTGCACA -2.077747  0.1443148 1.2094155        173           53
## TCTGATACACGTGT -1.896454  0.3670673 0.7782331         70           48
##                RNA_snn_res.0.8 letter.idents groups RNA_snn_res.1      CD7
## ATGCCAGAACGACT               0             A     g2             0 5.658486
## CATGGCCTGTGCAT               0             A     g1             0 5.465077
## GAACCTGATGAACC               1             B     g2             0 5.441920
## TGACTGGATTCTCA               0             A     g2             0 5.468990
## AGTCAGACTGCACA               0             A     g2             0 4.758809
## TCTGATACACGTGT               0             A     g1             0 4.968821
##                   CCL5      LCK S100A8     TYMP   S100A9 HLA-DPB1 MS4A1
## ATGCCAGAACGACT 0.00000 0.000000      0 0.000000 0.000000        0     0
## CATGGCCTGTGCAT 0.00000 5.869131      0 0.000000 4.776153        0     0
## GAACCTGATGAACC 0.00000 5.441920      0 0.000000 4.753095        0     0
## TGACTGGATTCTCA 5.06563 0.000000      0 0.000000 0.000000        0     0
## AGTCAGACTGCACA 0.00000 4.074201      0 4.074201 0.000000        0     0
## TCTGATACACGTGT 0.00000 4.968821      0 0.000000 0.000000        0     0
##                HLA-DQB1
## ATGCCAGAACGACT 4.968821
## CATGGCCTGTGCAT 0.000000
## GAACCTGATGAACC 0.000000
## TGACTGGATTCTCA 0.000000
## AGTCAGACTGCACA 0.000000
## TCTGATACACGTGT 0.000000
## color the cells by 'groups' info
cellobjs <- view3dCells(cells,
  x = "umap_1", y = "umap_2", z = "umap_3",
  color = "groups",
  colorFun = function(x) {
    ifelse(x == "g1", "red", "blue")
  },
  renderer = "none"
)

Plot the cells by rgl.

## not run to reduce the package size.
library(manipulateWidget)
clear3d() # Remove the earlier display
rglViewer(cellobjs, background = "white")
rglwidget()

Plot it by threeJs.

threeJsViewer(cellobjs)

We can also try to color the cells by a numeric column.

# plot it if interactive
if (interactive()) {
  view3dCells(cells,
    x = "umap_1", y = "umap_2", z = "umap_3",
    color = "nCount_RNA",
    colorFun = function(x, pal = colorRampPalette(c("black", "red"))(5)) {
      limits <- range(x)
      pal[findInterval(x, seq(limits[1], limits[2],
        length.out = length(pal) + 1
      ),
      all.inside = TRUE
      )]
    },
    renderer = "threejs"
  )
}

Advanced usage of threeJsViewer

layout

By default, the viewer built on three.js allows objects in a scene to be separated into layers based on tags. Users can easily toggle the visibility of these layers using the ‘toggle’ button in the controller. Additionally, layers can be grouped into two main categories (top and bottom), enabling the option to hide internal or auxiliary objects as needed.

In this example, we will move all the ticks and tss markers into bottom group. Please note that labels will not be affected by this methods.

for(i in seq_along(objs)){
  if(grepl('tick|arrow|cRE|tss', names(objs)[i])){
    objs[[i]]$layer <- 'bottom'
  }
}
if(interactive()){
  threeJsViewer(objs)
}

The threeJsViewer allows users to view two 3D structures side by side. It is recommended to align the 3D coordinates by alignCoor function before generating the threeJsGeometry objects for optimal comparison.

objs2 <- lapply(objs, function(.ele){
  .ele$side <- 'right'
  .ele
})
if(interactive()){
  threeJsViewer(objs, objs2)
}

Create objects from raw

Starting from the raw data, you will be prompted to provide the backbone to which materials will be attached. The backbone is a GRanges object containing the x, y, and z coordinates. Since the current resolution of Hi-C data is relatively low, we will first smooth the coordinates. The materials, also input as a GRanges object, will have their 3D positions derived from the backbone.

## simulate a backbone
library(GenomicRanges)
library(geomeTriD)
backbone <- GRanges(1, IRanges(seq(1, 10000, by=1000), width = 1000))
## set x, y, z position, we will use the torus knots equation
t <- seq(0, 2*pi, length.out=length(backbone))
p <- 3
q <- 2
r <- cos(p*t) + 2
backbone$x <- 2*r*cos(q*t)
backbone$y <- 2*r*sin(q*t)
backbone$z <- -2*sin(p*t)

## simulate the signals to be add
N1 <- 30
sig1 <- GRanges(1, IRanges(sample(seq.int(10000), N1), width = 10),
                score=runif(N1, min=1, max=10))
N2 <- 8
sig2 <- GRanges(1, IRanges(sample(seq.int(10000), N2), width = 1),
                score=runif(N2, min=0.05, max=1),
                shape=sample(c('dodecahedron', 'icosahedron',
                               'octahedron', 'tetrahedron'),
                             N2, replace = TRUE),
                color=sample(seq.int(7)[-1], N2, replace = TRUE))

## do smooth for the coordinates
backbone <- smooth3dPoints(backbone, resolution=10)

## create the line geometry
geo_backbone <- threeJsGeometry(
  x=c(backbone$x0, backbone$x1[length(backbone)]),
  y=c(backbone$y0, backbone$y1[length(backbone)]),
  z=c(backbone$z0, backbone$y1[length(backbone)]),
  colors = "black",
  type = "line",
  tag = "tagNameHere",
  properties= list(size = 2)
)

## create the sphere geometry for sig1
geo_sig1_sphere <- create3dGenomicSignals(
  GenoSig = sig1,
  targetObj = backbone,
  positionTransformFun = function(x) {
      x$y0 <- x$y0 + 0.5 # offset from y
      x$y1 <- x$y1 + 0.5
      x
    }, reverseGenomicSigs = FALSE,
    type = 'sphere',
    tag = 'head', name = 'head',
  color = c('blue', 'red'),
  radius = .25)
## create the cylinder geometry for sig1
geo_sig1_body <- create3dGenomicSignals(
  GenoSig = sig1,
  targetObj = backbone,
  positionTransformFun = function(x) {
      x$y0 <- x$y0 + 0.25 # offset from y
      x$y1 <- x$y1 + 0.25
      x
    }, reverseGenomicSigs = FALSE,
    type = 'cylinder',
    tag = 'body', name = 'body',
  height = .5, radiusTop = .05, radiusBottom = .15)
## create two small spheres
geo_sig1_ear1 <- create3dGenomicSignals(
  GenoSig = sig1,
  targetObj = backbone,
  positionTransformFun = function(x) {
      x$x0 <- x$x0 - 0.25 # offset from x
      x$x1 <- x$x1 - 0.25
      x$y0 <- x$y0 + 0.75 # offset from y
      x$y1 <- x$y1 + 0.75
      x
    }, reverseGenomicSigs = FALSE,
    type = 'sphere',
    tag = 'ear', name = 'ear1',
  color = c('blue', 'red'),
  radius = .1)
geo_sig1_ear2 <- create3dGenomicSignals(
  GenoSig = sig1,
  targetObj = backbone,
  positionTransformFun = function(x) {
      x$x0 <- x$x0 + 0.25 # offset from x
      x$x1 <- x$x1 + 0.25
      x$y0 <- x$y0 + 0.75 # offset from y
      x$y1 <- x$y1 + 0.75
      x
    }, reverseGenomicSigs = FALSE,
    type = 'sphere',
    tag = 'ear', name = 'ear2',
  color = c('blue', 'red'),
  radius = .1)
geo_sig1_nose <- create3dGenomicSignals(
  GenoSig = sig1,
  targetObj = backbone,
  positionTransformFun = function(x) {
      x$y0 <- x$y0 + 0.5 # offset from y
      x$y1 <- x$y1 + 0.5
      x$z0 <- x$z0 - 0.25 # offset from z
      x$z1 <- x$z1 - 0.25
      x
    }, reverseGenomicSigs = FALSE,
    type = 'capsule',
    tag = 'nose', name = 'nose',
  color = c('red', 'blue'),
  radius = .05, height=.05)

## create the icosahedron geometry for sig2
geo_sig2 <- lapply(seq_along(sig2), function(id){
  create3dGenomicSignals(
    GenoSig = sig2[id],
    targetObj = backbone,
    reverseGenomicSigs = FALSE,
    type=sig2[id]$shape,
    tag = 'sig2', name = as.character(id),
    color = sig2[id]$color,
    radius = sig2[id]$score
  )})

## create the a customized geometry by a json file
geo_json <- create3dGenomicSignals(
  GenoSig = GRanges(1, IRanges(5000, width=1), score=1),
  targetObj = backbone,
  type = 'json',
  tag = 'json', name='monkey',
  color = 'green',
  rotation = c(pi, 0, pi), ## we need to rotate the model to change the facing side
  path = system.file('extdata', 'suzanne_buffergeometry.json',
                     package = 'geomeTriD')
)
threeJsViewer(c(backbone=geo_backbone,
                geo_sig1_sphere, geo_sig1_body,
                geo_sig1_ear1, geo_sig1_ear2, geo_sig1_nose,
                geo_sig2, geo_json))

Session Info

sessionInfo()

R Under development (unstable) (2024-10-21 r87258) Platform: x86_64-pc-linux-gnu Running under: Ubuntu 24.04.1 LTS

Matrix products: default BLAS: /home/biocbuild/bbs-3.21-bioc/R/lib/libRblas.so LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.12.0

locale: [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
[3] LC_TIME=en_GB LC_COLLATE=C
[5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
[7] LC_PAPER=en_US.UTF-8 LC_NAME=C
[9] LC_ADDRESS=C LC_TELEPHONE=C
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C

time zone: America/New_York tzcode source: system (glibc)

attached base packages: [1] grid stats4 stats graphics grDevices utils datasets [8] methods base

other attached packages: [1] trackViewer_1.43.1
[2] rgl_1.3.12
[3] InteractionSet_1.35.0
[4] SummarizedExperiment_1.37.0
[5] MatrixGenerics_1.19.0
[6] matrixStats_1.4.1
[7] org.Hs.eg.db_3.20.0
[8] TxDb.Hsapiens.UCSC.hg19.knownGene_3.2.2 [9] GenomicFeatures_1.59.1
[10] AnnotationDbi_1.69.0
[11] Biobase_2.67.0
[12] GenomicRanges_1.59.0
[13] GenomeInfoDb_1.43.0
[14] IRanges_2.41.0
[15] S4Vectors_0.45.1
[16] BiocGenerics_0.53.2
[17] generics_0.1.3
[18] geomeTriD_1.1.1

loaded via a namespace (and not attached): [1] strawr_0.0.92 RColorBrewer_1.1-3 rstudioapi_0.17.1
[4] jsonlite_1.8.9 magrittr_2.0.3 rmarkdown_2.29
[7] BiocIO_1.17.0 zlibbioc_1.53.0 vctrs_0.6.5
[10] memoise_2.0.1 Rsamtools_2.23.0 RCurl_1.98-1.16
[13] base64enc_0.1-3 htmltools_0.5.8.1 S4Arrays_1.7.1
[16] progress_1.2.3 plotrix_3.8-4 curl_6.0.0
[19] Rhdf5lib_1.29.0 rhdf5_2.51.0 SparseArray_1.7.1
[22] Formula_1.2-5 sass_0.4.9 bslib_0.8.0
[25] htmlwidgets_1.6.4 Gviz_1.51.0 httr2_1.0.6
[28] cachem_1.1.0 GenomicAlignments_1.43.0 igraph_2.1.1
[31] lifecycle_1.0.4 pkgconfig_2.0.3 Matrix_1.7-1
[34] R6_2.5.1 fastmap_1.2.0 GenomeInfoDbData_1.2.13 [37] digest_0.6.37 colorspace_2.1-1 Hmisc_5.2-0
[40] RSQLite_2.3.7 filelock_1.0.3 fansi_1.0.6
[43] httr_1.4.7 abind_1.4-8 compiler_4.5.0
[46] bit64_4.5.2 htmlTable_2.4.3 backports_1.5.0
[49] BiocParallel_1.41.0 DBI_1.2.3 biomaRt_2.63.0
[52] MASS_7.3-61 rappdirs_0.3.3 DelayedArray_0.33.1
[55] rjson_0.2.23 tools_4.5.0 foreign_0.8-87
[58] nnet_7.3-19 glue_1.8.0 restfulr_0.0.15
[61] rhdf5filters_1.19.0 checkmate_2.3.2 cluster_2.1.6
[64] gtable_0.3.6 BSgenome_1.75.0 ensembldb_2.31.0
[67] data.table_1.16.2 hms_1.1.3 xml2_1.3.6
[70] utf8_1.2.4 XVector_0.47.0 pillar_1.9.0
[73] stringr_1.5.1 dplyr_1.1.4 BiocFileCache_2.15.0
[76] lattice_0.22-6 deldir_2.0-4 rtracklayer_1.67.0
[79] bit_4.5.0 biovizBase_1.55.0 tidyselect_1.2.1
[82] Biostrings_2.75.1 knitr_1.49 gridExtra_2.3
[85] ProtGenerics_1.39.0 xfun_0.49 stringi_1.8.4
[88] UCSC.utils_1.3.0 lazyeval_0.2.2 yaml_2.3.10
[91] evaluate_1.0.1 codetools_0.2-20 interp_1.1-6
[94] tibble_3.2.1 BiocManager_1.30.25 cli_3.6.3
[97] rpart_4.1.23 munsell_0.5.1 jquerylib_0.1.4
[100] dichromat_2.0-0.1 Rcpp_1.0.13-1 grImport_0.9-7
[103] dbplyr_2.5.0 png_0.1-8 XML_3.99-0.17
[106] parallel_4.5.0 ggplot2_3.5.1 blob_1.2.4
[109] prettyunits_1.2.0 jpeg_0.1-10 latticeExtra_0.6-30
[112] AnnotationFilter_1.31.0 bitops_1.0-9 txdbmaker_1.3.0
[115] VariantAnnotation_1.53.0 scales_1.3.0 crayon_1.5.3
[118] BiocStyle_2.35.0 rlang_1.1.4 KEGGREST_1.47.0