Figure S5 showcases the geomeTriD
package, demonstrating
how it presents 3D models along with multiple genomic signals mapped
onto single-cell 3D structures.
library(geomeTriD)
library(geomeTriD.documentation)
library(GenomicRanges)
library(GenomeInfoDb)
library(colorRamps)
library(TxDb.Mmusculus.UCSC.mm10.knownGene)
library(org.Mm.eg.db)
library(geometry)
Here we present 3D genome models with integrated genomic signals derived from Tri-omic, also known as ChAIR (capture of chromatin Accessibility, Interaction, and RNA profiles). This method enables simultaneous mapping of chromatin accessibility, chromatin interactions, and gene expression. Paired-end tag (PET) data are used to reconstruct 3D genome structures, while the accompanying RNA-seq and ATAC-seq signals are visualized along these models.
## plot region
range <- GRanges('chrX:1-20000000')
## prepare features
feature.gr <- getFeatureGR(txdb = TxDb.Mmusculus.UCSC.mm10.knownGene,
org = org.Mm.eg.db,
range = range)
## 66 genes were dropped because they have exons located on both strands of the
## same reference sequence or on more than one reference sequence, so cannot be
## represented by a single genomic range.
## Use 'single.strand.genes.only=FALSE' to get all the genes in a GRangesList
## object, or use suppressMessages() to suppress this message.
## 'select()' returned 1:1 mapping between keys and columns
## load the 3D structure for PET data
stage <- c('G1', 'S', 'G2M')
extdata <- system.file('extdata', 'ChAIR', package = 'geomeTriD.documentation')
ChAIR_PET_m <- import3dg(file.path(extdata, 'PET', paste0('patski.allele.', stage, '_2_m.pairs.chrX.3dg.gz')))
ChAIR_PET_p <- import3dg(file.path(extdata, 'PET', paste0('patski.allele.', stage, '_2_p.pairs.chrX.3dg.gz')))
## get the chrX coordinates for maternal and paternal
ChAIR_PET_m <- lapply(ChAIR_PET_m, function(.ele) {
seqlevelsStyle(.ele) <- 'UCSC'
.ele$parental <- NULL
subsetByOverlaps(.ele, range)
})
ChAIR_PET_p <- lapply(ChAIR_PET_p, function(.ele) {
seqlevelsStyle(.ele) <- 'UCSC'
.ele$parental <- NULL
subsetByOverlaps(.ele, range)
})
# import the signals for ATAC-seq and RNA-seq for maternal and paternal
M <- lapply(stage, function(cc){ ## maternal
importGenomicSigs(c(ATAC=file.path(extdata, 'ATAC', paste0('patski.allele.', cc, '_2.M.bw')),
RNA=file.path(extdata, 'RNA', paste0('patski.allele.', cc, '_2.M.bw'))),
range = range,
cols = c('darkgreen', 'darkred'),
format = 'BigWig')
})
P <- lapply(stage, function(cc){ ## paternal
importGenomicSigs(c(ATAC=file.path(extdata, 'ATAC', paste0('patski.allele.', cc, '_2.P.bw')),
RNA=file.path(extdata, 'RNA', paste0('patski.allele.', cc, '_2.P.bw'))),
range = range,
cols = c('darkgreen', 'darkred'),
format = 'BigWig')
})
## set backbone color, make it easy to catch the genomic coordinates
resolution <- 3
backbone_colors <- rev(rainbow(n=resolution*length(ChAIR_PET_m[[1]])))
## only label the genes with high expression
labelHighExpGene <- function(sig){
this.feature.gr <- feature.gr
expressed <- sig$RNA$dat[sig$RNA$dat$score>100]
this.feature.gr$label[countOverlaps(feature.gr, expressed)==0] <- NA
## remove the genes with big size
this.feature.gr$label[width(this.feature.gr)>100000] <- NA
## only show the first gene label if multiple high expressed gene
## in the same region
l.rle <- rle(!is.na(this.feature.gr$label))
l.rle$values[l.rle$lengths<=5] <- TRUE ## merge the region with small gap
l.rle <- rle(inverse.rle(l.rle))
l <- cumsum(l.rle$lengths)
this.feature.gr$label[-l[l.rle$values]] <- NA
return(this.feature.gr)
}
## create threeJsGeometry objects for maternal and paternal cells
M_cells <- mapply(ChAIR_PET_m, M, FUN=function(model, sig){
cell <- view3dStructure(model,
feature.gr = labelHighExpGene(sig),
genomicSigs = sig,
signalTransformFun = log1p,
lwd.maxGenomicSigs = 8,
reverseGenomicSigs = FALSE,
renderer = 'none',
resolution = resolution,
col.backbone = rev(rainbow(n=resolution*length(model))),
lwd.backbone = 0.25,
lwd.gene = 1,
region = range,
show_coor = FALSE,
cluster3Dpoints = TRUE)
}, SIMPLIFY = FALSE)
P_cells <- mapply(ChAIR_PET_p, P, FUN=function(model, sig){
cell <- view3dStructure(model,
feature.gr = labelHighExpGene(sig),
genomicSigs = sig,
signalTransformFun = log1p,
lwd.maxGenomicSigs = 8,
reverseGenomicSigs = FALSE,
renderer = 'none',
resolution = resolution,
col.backbone = rev(rainbow(n=resolution*length(model))),
lwd.backbone = 0.25,
lwd.gene = 1,
region = range,
show_coor = FALSE,
cluster3Dpoints = TRUE)
}, SIMPLIFY = FALSE)
## show the maternal and paternal structures side by side
showPairs(M_cells[[1]], P_cells[[1]], title=c('mat G1', 'pat G1')) #G1
## check the size
getV <- function(points){
vol <- convhulln(as.matrix(mcols(points)), options='Fa')$vol
}
sapply(ChAIR_PET_m, getV)
## [1] 1.3883935 2.1113253 0.6169364
sapply(ChAIR_PET_p, getV)
## [1] 0.7920844 1.2108770 0.3453040
## R version 4.5.1 (2025-06-13)
## Platform: x86_64-pc-linux-gnu
## Running under: Ubuntu 24.04.2 LTS
##
## Matrix products: default
## BLAS: /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3
## LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.26.so; LAPACK version 3.12.0
##
## locale:
## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
## [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
## [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
## [7] LC_PAPER=en_US.UTF-8 LC_NAME=C
## [9] LC_ADDRESS=C LC_TELEPHONE=C
## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
##
## time zone: Etc/UTC
## tzcode source: system (glibc)
##
## attached base packages:
## [1] grid stats4 stats graphics grDevices utils datasets
## [8] methods base
##
## other attached packages:
## [1] GenomeInfoDb_1.45.7
## [2] geometry_0.5.2
## [3] org.Mm.eg.db_3.21.0
## [4] TxDb.Mmusculus.UCSC.mm10.knownGene_3.10.0
## [5] GenomicFeatures_1.61.4
## [6] AnnotationDbi_1.71.0
## [7] Biobase_2.69.0
## [8] colorRamps_2.3.4
## [9] GenomicRanges_1.61.1
## [10] Seqinfo_0.99.1
## [11] IRanges_2.43.0
## [12] S4Vectors_0.47.0
## [13] BiocGenerics_0.55.0
## [14] generics_0.1.4
## [15] geomeTriD.documentation_0.0.5
## [16] geomeTriD_1.3.15
##
## loaded via a namespace (and not attached):
## [1] BiocIO_1.19.0 bitops_1.0-9
## [3] filelock_1.0.3 tibble_3.3.0
## [5] R.oo_1.27.1 XML_3.99-0.18
## [7] rpart_4.1.24 lifecycle_1.0.4
## [9] httr2_1.1.2 aricode_1.0.3
## [11] globals_0.18.0 lattice_0.22-7
## [13] ensembldb_2.33.1 MASS_7.3-65
## [15] backports_1.5.0 magrittr_2.0.3
## [17] Hmisc_5.2-3 sass_0.4.10
## [19] rmarkdown_2.29 jquerylib_0.1.4
## [21] yaml_2.3.10 plotrix_3.8-4
## [23] Gviz_1.53.1 DBI_1.2.3
## [25] RColorBrewer_1.1-3 abind_1.4-8
## [27] R.utils_2.13.0 AnnotationFilter_1.33.0
## [29] biovizBase_1.57.1 RCurl_1.98-1.17
## [31] rgl_1.3.24 nnet_7.3-20
## [33] VariantAnnotation_1.55.1 rappdirs_0.3.3
## [35] grImport_0.9-7 listenv_0.9.1
## [37] parallelly_1.45.0 pkgdown_2.1.3
## [39] codetools_0.2-20 DelayedArray_0.35.2
## [41] xml2_1.3.8 tidyselect_1.2.1
## [43] UCSC.utils_1.5.0 farver_2.1.2
## [45] matrixStats_1.5.0 BiocFileCache_2.99.5
## [47] base64enc_0.1-3 GenomicAlignments_1.45.1
## [49] jsonlite_2.0.0 trackViewer_1.45.1
## [51] progressr_0.15.1 Formula_1.2-5
## [53] systemfonts_1.2.3 dbscan_1.2.2
## [55] tools_4.5.1 progress_1.2.3
## [57] ragg_1.4.0 strawr_0.0.92
## [59] Rcpp_1.1.0 glue_1.8.0
## [61] gridExtra_2.3 SparseArray_1.9.0
## [63] xfun_0.52 MatrixGenerics_1.21.0
## [65] dplyr_1.1.4 fastmap_1.2.0
## [67] latticeExtra_0.6-30 rhdf5filters_1.21.0
## [69] digest_0.6.37 R6_2.6.1
## [71] textshaping_1.0.1 colorspace_2.1-1
## [73] jpeg_0.1-11 dichromat_2.0-0.1
## [75] biomaRt_2.65.0 RSQLite_2.4.1
## [77] R.methodsS3_1.8.2 data.table_1.17.8
## [79] rtracklayer_1.69.1 prettyunits_1.2.0
## [81] InteractionSet_1.37.0 httr_1.4.7
## [83] htmlwidgets_1.6.4 S4Arrays_1.9.1
## [85] pkgconfig_2.0.3 gtable_0.3.6
## [87] blob_1.2.4 XVector_0.49.0
## [89] htmltools_0.5.8.1 ProtGenerics_1.41.0
## [91] clue_0.3-66 scales_1.4.0
## [93] png_0.1-8 knitr_1.50
## [95] rstudioapi_0.17.1 rjson_0.2.23
## [97] checkmate_2.3.2 magic_1.6-1
## [99] curl_6.4.0 cachem_1.1.0
## [101] rhdf5_2.53.1 stringr_1.5.1
## [103] parallel_4.5.1 foreign_0.8-90
## [105] restfulr_0.0.16 desc_1.4.3
## [107] pillar_1.11.0 vctrs_0.6.5
## [109] RANN_2.6.2 dbplyr_2.5.0
## [111] cluster_2.1.8.1 htmlTable_2.4.3
## [113] evaluate_1.0.4 cli_3.6.5
## [115] compiler_4.5.1 Rsamtools_2.25.1
## [117] rlang_1.1.6 crayon_1.5.3
## [119] future.apply_1.20.0 interp_1.1-6
## [121] fs_1.6.6 stringi_1.8.7
## [123] deldir_2.0-4 BiocParallel_1.43.4
## [125] txdbmaker_1.5.6 Biostrings_2.77.2
## [127] lazyeval_0.2.2 Matrix_1.7-3
## [129] BSgenome_1.77.1 hms_1.1.3
## [131] bit64_4.6.0-1 future_1.58.0
## [133] ggplot2_3.5.2 Rhdf5lib_1.31.0
## [135] KEGGREST_1.49.1 SummarizedExperiment_1.39.1
## [137] igraph_2.1.4 memoise_2.0.1
## [139] bslib_0.9.0 bit_4.6.0