tTEscanR tRNA-Specific Preprocessing Module


1. Overview

tTEscanR includes a dedicated preprocessing module that provides multiple functions for generating ready-to-use data count matrices. The primary goal of this module is to facilitate the transformation from (sc)ATAC-seq count matrices to tRNA abundance count matrices where tRNA genes are the rows and the conditions the columns. Additionally, it helps annotating the tRNA genes.

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

BiocManager::install("tTEscanR")
library(tTEscanR)

To illustrate the functionality of the tRNA specific preprocessing module we generated a toy example dataset representing a peak count matrix where the fragment regions are placed as rows and the samples as columns. We have also defined the corresponding metadata.

library(Matrix)

# Parameters
num_peaks <- 100
num_cells <- 20 # Increased to pass min.cells = 10
set.seed(42)

# Create peak names with "-" separator
chroms <- sample(paste0("chr", 1:3), num_peaks, replace = TRUE)
starts <- seq(1000, by = 5000, length.out = num_peaks)
ends <- starts + 300
peak_names <- paste(chroms, starts, ends, sep = "-")

# Create a sparse matrix
counts <- Matrix(
    rpois(num_peaks * num_cells, lambda = 5),
    nrow = num_peaks,
    ncol = num_cells,
    sparse = TRUE
)

rownames(counts) <- peak_names
colnames(counts) <- paste0("Cell_", seq_len(num_cells))

saveRDS(counts, "foo.RDS")
library(dplyr)
library(Rsamtools)
#> Loading required package: Seqinfo
#> Loading required package: BiocGenerics
#> Loading required package: generics
#> 
#> Attaching package: 'generics'
#> The following object is masked from 'package:dplyr':
#> 
#>     explain
#> The following objects are masked from 'package:base':
#> 
#>     as.difftime, as.factor, as.ordered, intersect, is.element, setdiff,
#>     setequal, union
#> 
#> Attaching package: 'BiocGenerics'
#> The following object is masked from 'package:dplyr':
#> 
#>     combine
#> The following object is masked from 'package:tTEscanR':
#> 
#>     updateObject
#> The following objects are masked from 'package:stats':
#> 
#>     IQR, mad, sd, var, xtabs
#> The following object is masked from 'package:utils':
#> 
#>     data
#> The following objects are masked from 'package:base':
#> 
#>     anyDuplicated, aperm, append, as.data.frame, basename, cbind,
#>     colnames, dirname, do.call, duplicated, eval, evalq, Filter, Find,
#>     get, grep, grepl, is.unsorted, lapply, Map, mapply, match, mget,
#>     order, paste, pmax, pmax.int, pmin, pmin.int, Position, rank,
#>     rbind, Reduce, rownames, sapply, saveRDS, scale, sequence, table,
#>     tapply, transform, unique, unsplit, which.max, which.min
#> Loading required package: GenomicRanges
#> Loading required package: stats4
#> Loading required package: S4Vectors
#> 
#> Attaching package: 'S4Vectors'
#> The following objects are masked from 'package:Matrix':
#> 
#>     expand, unname
#> The following objects are masked from 'package:dplyr':
#> 
#>     first, rename
#> The following object is masked from 'package:utils':
#> 
#>     findMatches
#> The following objects are masked from 'package:base':
#> 
#>     expand.grid, I, unname
#> Loading required package: IRanges
#> 
#> Attaching package: 'IRanges'
#> The following objects are masked from 'package:dplyr':
#> 
#>     collapse, desc, slice
#> Loading required package: Biostrings
#> Loading required package: XVector
#> 
#> Attaching package: 'Biostrings'
#> The following object is masked from 'package:base':
#> 
#>     strsplit

# Generate fragments based on our counts matrix
fragment_list <- list()
for (i in 1:ncol(counts)) {
    cell_name <- colnames(counts)[i]
    for (j in 1:nrow(counts)) {
        cnt <- counts[j, i]
        if (cnt > 0) {
            parts <- strsplit(rownames(counts)[j], "-", fixed = TRUE)[[1]]
            for (k in 1:cnt) {
                fragment_list[[length(fragment_list) + 1]] <- data.frame(
                    chr = parts[1],
                    start = as.numeric(parts[2]) + k,
                    end = as.numeric(parts[3]) - k,
                    cell = cell_name,
                    count = 1
                )
            }
        }
    }
}

fragments_df <- bind_rows(fragment_list) %>%
    arrange(chr, start) # Sorting is mandatory for indexing

# Write to a temporary text file
temp_txt <- "foo.fragments.txt"
write.table(
    fragments_df, temp_txt,
    sep = "\t",
    row.names = FALSE, col.names = FALSE, quote = FALSE
)

# Bgzip compress and index (Requires Rsamtools)
# This creates foo.fragments.txt.gz and foo.fragments.txt.gz.tbi
bgzip(temp_txt, dest = "foo.fragments.txt.gz", overwrite = TRUE)
#> [1] "foo.fragments.txt.gz"
indexTabix("foo.fragments.txt.gz", format = "bed")
#> [1] "foo.fragments.txt.gz.tbi"

# Clean up the uncompressed temp file
file.remove(temp_txt)
#> [1] TRUE
library(Signac)
library(Seurat)
#> Loading required package: SeuratObject
#> Loading required package: sp
#> 
#> Attaching package: 'sp'
#> The following object is masked from 'package:IRanges':
#> 
#>     %over%
#> 'SeuratObject' was built under R 4.6.0 but the current version is
#> 4.6.2; it is recomended that you reinstall 'SeuratObject' as the ABI
#> for R may have changed
#> 'SeuratObject' was built with package 'Matrix' 1.7.5 but the current
#> version is 1.7.6; it is recomended that you reinstall 'SeuratObject' as
#> the ABI for 'Matrix' may have changed
#> 
#> Attaching package: 'SeuratObject'
#> The following object is masked from 'package:Biostrings':
#> 
#>     intersect
#> The following object is masked from 'package:GenomicRanges':
#> 
#>     intersect
#> The following object is masked from 'package:IRanges':
#> 
#>     intersect
#> The following object is masked from 'package:S4Vectors':
#> 
#>     intersect
#> The following object is masked from 'package:Seqinfo':
#> 
#>     intersect
#> The following object is masked from 'package:BiocGenerics':
#> 
#>     intersect
#> The following objects are masked from 'package:base':
#> 
#>     intersect, t
#> v5.6 adds significant improvements in speed and efficiency, particularly for large datasets.
#> For more information, see https://satijalab.org/seurat/articles/announcements.

counts_loaded <- readRDS("foo.RDS")
fragment_file <- "foo.fragments.txt.gz"

chrom_assay <- CreateChromatinAssay(
    counts = counts_loaded,
    sep = c("-", "-"),
    fragments = fragment_file,
    min.cells = 10,
    min.features = 0
)
#> Computing hash

chrom_obj <- CreateSeuratObject(
    counts = chrom_assay,
    assay = "peaks"
)

print(chrom_obj)
#> An object of class Seurat 
#> 100 features across 20 samples within 1 assay 
#> Active assay: peaks (100 features, 0 variable features)
#>  2 layers present: counts, data

2. Obtaining the tRNA matrix

The first step is to generate the tRNA matrix and translate the peak fragments into tRNA gene names.

tRNA_matrix <- tRNAGetMatrix(
    data = chrom_obj, assay = "peaks", confidence_set = NULL, species = "hg38"
)
#> 1 . Importing the high-confidence tRNA annotations.
#> The default hg38 'confidence_set' will be used.
#> 1 . COMPLETED
#> 2 . Filtering tRNA genes with unknown annotations.
#> Loading required namespace: Structstrings
#> The default hg38 'tRNA_name_map' will be used.
#> 2 . COMPLETED
#> 3 . Finding overlaps and aggregating tRNA counts.
#> Extracting reads overlapping genomic regions
#> 3 . COMPLETED

3. Identifying the optimal tRNA cutoff

#> R version 4.6.2 (2026-10-29)
#> Platform: x86_64-pc-linux-gnu
#> Running under: Ubuntu 26.04.1 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.32.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] stats4    stats     graphics  grDevices utils     datasets  methods  
#> [8] base     
#> 
#> other attached packages:
#>  [1] Seurat_5.6.0         SeuratObject_5.4.0   sp_2.2-4            
#>  [4] Signac_1.17.1        Rsamtools_2.29.0     Biostrings_2.81.9   
#>  [7] XVector_0.53.0       GenomicRanges_1.65.4 IRanges_2.47.5      
#> [10] S4Vectors_0.51.10    Seqinfo_1.3.2        BiocGenerics_0.59.12
#> [13] generics_0.1.4       Matrix_1.7-6         dplyr_1.2.1         
#> [16] biomaRt_2.69.6       tTEscanR_0.99.2      BiocStyle_2.41.0    
#> 
#> loaded via a namespace (and not attached):
#>   [1] RcppAnnoy_0.0.23            later_1.4.8                
#>   [3] splines_4.6.2               bitops_1.1-0               
#>   [5] filelock_1.0.3              tibble_3.3.1               
#>   [7] polyclip_1.10-7             fastDummies_1.7.6          
#>   [9] lifecycle_1.0.5             httr2_1.3.0                
#>  [11] rstatix_1.1.0               doParallel_1.0.17          
#>  [13] globals_0.20.0              lattice_0.23-1             
#>  [15] MASS_7.3-66                 MultiAssayExperiment_1.39.1
#>  [17] backports_1.5.1             magrittr_2.0.5             
#>  [19] plotly_4.12.1               sass_0.4.10                
#>  [21] rmarkdown_2.32              jquerylib_0.1.4            
#>  [23] yaml_2.3.12                 httpuv_1.6.17              
#>  [25] otel_0.2.0                  sctransform_0.4.3          
#>  [27] spam_2.11-4                 spatstat.sparse_3.2-0      
#>  [29] reticulate_1.47.0           cowplot_1.2.0              
#>  [31] pbapply_1.7-5               DBI_1.3.0                  
#>  [33] buildtools_1.0.0            RColorBrewer_1.1-3         
#>  [35] abind_1.4-8                 Rtsne_0.17                 
#>  [37] purrr_1.2.2                 circlize_0.4.18            
#>  [39] ggrepel_0.9.8               irlba_2.4.1                
#>  [41] spatstat.utils_3.2-5        listenv_1.1.0              
#>  [43] maketools_1.3.2             goftest_1.2-3              
#>  [45] RSpectra_0.16-2             spatstat.random_3.5-2      
#>  [47] fitdistrplus_1.2-6          parallelly_1.50.0          
#>  [49] codetools_0.2-20            DelayedArray_0.39.8        
#>  [51] RcppRoll_0.4.0              tidyselect_1.2.1           
#>  [53] shape_1.4.6.1               UCSC.utils_1.9.0           
#>  [55] farver_2.1.2                viridis_0.6.5              
#>  [57] spatstat.explore_3.8-3      matrixStats_1.5.0          
#>  [59] BiocFileCache_3.3.1         jsonlite_2.0.0             
#>  [61] GetoptLong_1.1.1            progressr_1.1.0            
#>  [63] Formula_1.2-6               ggridges_0.5.7             
#>  [65] survival_3.8-12             iterators_1.0.14           
#>  [67] foreach_1.5.2               tools_4.6.2                
#>  [69] progress_1.2.3              ica_1.0-3                  
#>  [71] Rcpp_1.1.2                  glue_1.8.1                 
#>  [73] gridExtra_2.3.1             SparseArray_1.13.4         
#>  [75] BiocBaseUtils_1.15.1        xfun_0.62                  
#>  [77] DESeq2_1.53.7               MatrixGenerics_1.25.0      
#>  [79] GenomeInfoDb_1.49.2         withr_3.0.3                
#>  [81] BiocManager_1.30.27         fastmap_1.2.0              
#>  [83] digest_0.6.39               mime_0.13                  
#>  [85] R6_2.6.1                    colorspace_2.1-4           
#>  [87] scattermore_1.2             tensor_1.5.1               
#>  [89] spatstat.data_3.1-9         RSQLite_3.53.3             
#>  [91] tidyr_1.3.2                 data.table_1.18.6.1        
#>  [93] Structstrings_1.29.0        htmlwidgets_1.6.4          
#>  [95] prettyunits_1.2.0           httr_1.4.9                 
#>  [97] S4Arrays_1.13.2             uwot_0.2.5                 
#>  [99] pkgconfig_2.0.3             gtable_0.3.6               
#> [101] blob_1.3.0                  ComplexHeatmap_2.29.0      
#> [103] lmtest_0.9-40               S7_0.2.2                   
#> [105] sys_3.4.3                   htmltools_0.5.9            
#> [107] carData_3.0-6               dotCall64_1.2              
#> [109] clue_0.3-68                 scales_1.4.0               
#> [111] Biobase_2.73.2              dendsort_0.3.4             
#> [113] png_0.1-9                   spatstat.univar_3.2-0      
#> [115] knitr_1.52                  reshape2_1.4.5             
#> [117] rjson_0.2.23                nlme_3.1-172               
#> [119] curl_8.1.0                  cachem_1.1.0               
#> [121] zoo_1.9-1                   GlobalOptions_0.1.4        
#> [123] stringr_1.6.0               KernSmooth_2.23-27         
#> [125] parallel_4.6.2              miniUI_0.1.2               
#> [127] AnnotationDbi_1.75.2        pillar_1.11.1              
#> [129] grid_4.6.2                  vctrs_0.7.3                
#> [131] RANN_2.6.3                  promises_1.5.0             
#> [133] ggpubr_1.0.0                car_3.1-5                  
#> [135] dbplyr_2.6.0                xtable_1.8-8               
#> [137] cluster_2.1.8.3             evaluate_1.0.5             
#> [139] cli_3.6.6                   locfit_1.5-9.12            
#> [141] compiler_4.6.2              rlang_1.3.0                
#> [143] crayon_1.5.3                future.apply_1.21.0        
#> [145] ggsignif_0.6.4              labeling_0.4.3             
#> [147] plyr_1.8.9                  stringi_1.8.9              
#> [149] deldir_2.0-4                viridisLite_0.4.3          
#> [151] BiocParallel_1.47.0         spatstat.geom_3.8-3        
#> [153] RcppHNSW_0.7.0              hms_1.1.4                  
#> [155] patchwork_1.3.2             sparseMatrixStats_1.25.0   
#> [157] bit64_4.8.6                 future_1.82.0              
#> [159] ggplot2_4.0.3               shiny_1.14.0               
#> [161] KEGGREST_1.53.6             SummarizedExperiment_1.43.0
#> [163] ROCR_1.0-12                 igraph_2.3.4               
#> [165] broom_1.0.13                memoise_2.0.1              
#> [167] bslib_0.12.0                fastmatch_1.1-8            
#> [169] bit_4.6.0