Figure S5

Figure S5 showcases the geomeTriD package, demonstrating how it presents 3D models along with multiple genomic signals mapped onto single-cell 3D structures.

Load Libraries

Present single cell 3D structure for ChAIR data

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
showPairs(M_cells[[2]], P_cells[[2]], title=c('mat S', 'pat S')) #S
showPairs(M_cells[[3]], P_cells[[3]], title=c('mat G2M', 'pat G2M')) #G2M
## 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

SessionInfo

## 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