The epitranscriptome includes all post-transcriptional modifications of the RNA and describes and additional layer of information encoded on RNA. Like the term epigenome it is not about a change in nucleotide sequences, but the addition of functional elements through modifications.
With the development of high throughput detection strategies for specific RNA modifications, such as miCLIP and Pseudo-Seq amongst other, a large number of modified positions have been identified and were summarized via the RMBase project (Xuan et al. 2017; Sun et al. 2015) project.
To make these information avaialble within the Bioconductor universe
EpiTxDb
was developed, which facilitates the storage of
epitranscriptomic information. More specifically, it can keep track of
modification identity, position, the enzyme for introducing it on the
RNA, a specifier which determines the position on the RNA to be modified
and the literature references each modification is associated with.
The class EpiTxDb
is the class for storing the
epitranscriptomic data. It inherits the inner workings of
AnnotationDb
class from the AnnotationDbi
package.
As an example for the vignette the snoRNAdb data (Lestrade and Weber
2006) from the EpiTxDb.Hs.hg38
package will be
used. The data is stored in the AnnotationHub
and is
downloaded and cached upon the first request.
## downloading 1 resources
## retrieving 1 resource
## loading from cache
## EpiTxDb object:
## # Db type: EpiTxDb
## # Supporting package: EpiTxDb
## # Data source: snoRNAdb
## # Organism: Homo sapiens
## # Genome: hg38
## # Coordinates: per Transcript
## # Nb of modifications: 235
## # Db created by: EpiTxDb package from Bioconductor
## # Creation time: 2020-02-26 10:34:30 +0100 (Wed, 26 Feb 2020)
## # EpiTxDb version at creation time: 0.99.0
## # RSQLite version at creation time: 2.2.0
## # DBSCHEMAVERSION: 1.0
As expected for an AnnotationDb
class the general
accessors are available.
## [1] "MODID" "MODNAME" "MODSTRAND" "MODTYPE"
## [5] "REF" "REFTYPE" "RXENSEMBL" "RXENSEMBLTRANS"
## [9] "RXENTREZID" "RXGENENAME" "SNID" "SNNAME"
## [13] "SPECENSEMBL" "SPECENSEMBLTRANS" "SPECENTREZID" "SPECGENENAME"
## [17] "SPECTYPE"
## [1] "MODEND" "MODID" "MODNAME" "MODSTART"
## [5] "MODSTRAND" "MODTYPE" "REF" "REFID"
## [9] "REFTYPE" "RXENSEMBL" "RXENSEMBLTRANS" "RXENTREZID"
## [13] "RXGENENAME" "RXID" "RXRANK" "SNID"
## [17] "SNNAME" "SPECENSEMBL" "SPECENSEMBLTRANS" "SPECENTREZID"
## [21] "SPECGENENAME" "SPECID" "SPECTYPE"
## [1] "1" "2" "3" "4" "5" "6"
select(etdb, keys = "1",
columns = c("MODNAME","MODTYPE","MODSTART","MODSTRAND","SNNAME",
"RXGENENAME","SPECTYPE","SPECGENENAME"),
keytype = "MODID")
## 'select()' returned 1:1 mapping between keys and columns
## MODID MODNAME MODTYPE MODSTART MODSTRAND SNNAME RXGENENAME SPECTYPE
## 1 1 Um_14 Um 14 + NR_003285 fibrillarin snoRNA
## SPECGENENAME
## 1 SNORD71
The columns with the prefix RX
or SPEC
reference the reaction enzyme and the location specifier. This can be
the same information, but for ribosomal modifications from the snoRNAdb
it is of course fibrillarin and a snoRNA.
In addition the following accessor for metadata are available as well.
## [1] "Homo sapiens"
## [1] "Homo sapiens"
## [1] "NR_003285" "NR_003286" "NR_003287" "NR_004430" "NR_002716" "NR_003925"
## [7] "NR_002756" "NR_004394" "NR_029422"
The specialized accessors are modifications()
and
modificationsBy()
. modifications()
allows for
filtering results, whereas modificationsBy()
returns all
the modifications in batches separated by certain information.
modifications(etdb, columns = c("mod_id","mod_type","mod_name",
"rx_genename","spec_genename",
"ref_type","ref"),
filter = list(mod_id = 1:3))
## GRanges object with 3 ranges and 7 metadata columns:
## seqnames ranges strand | mod_id mod_type mod_name
## <Rle> <IRanges> <Rle> | <integer> <character> <character>
## [1] NR_003285 14 + | 1 Um Um_14
## [2] NR_003285 55 + | 2 Y Y_55
## [3] NR_003285 69 + | 3 Y Y_69
## rx_genename spec_genename ref_type ref
## <CharacterList> <CharacterList> <CharacterList> <CharacterList>
## [1] fibrillarin SNORD71 PMID 16381836
## [2] dyskerin pseudouridi.. SNORA72 PMID 16381836
## [3] dyskerin pseudouridi.. SNORA69 PMID 16381836
## -------
## seqinfo: 9 sequences from hg38 genome; no seqlengths
## GRangesList object of length 9:
## $NR_003285
## GRanges object with 4 ranges and 3 metadata columns:
## seqnames ranges strand | mod_id mod mod_name
## <Rle> <IRanges> <Rle> | <integer> <character> <character>
## [1] NR_003285 14 + | 1 Um Um_14
## [2] NR_003285 55 + | 2 Y Y_55
## [3] NR_003285 69 + | 3 Y Y_69
## [4] NR_003285 75 + | 4 Gm Gm_75
## -------
## seqinfo: 9 sequences from hg38 genome; no seqlengths
##
## ...
## <8 more elements>
## GRangesList object of length 5:
## $Am
## GRanges object with 39 ranges and 3 metadata columns:
## seqnames ranges strand | mod mod_id mod_name
## <Rle> <IRanges> <Rle> | <character> <integer> <character>
## [1] NR_003286 27 + | Am 5 Am_27
## [2] NR_003286 99 + | Am 9 Am_99
## [3] NR_003286 159 + | Am 15 Am_159
## [4] NR_003286 166 + | Am 16 Am_166
## [5] NR_003286 468 + | Am 25 Am_468
## ... ... ... ... . ... ... ...
## [35] NR_002716 30 + | Am 207 Am_30
## [36] NR_003925 65 + | Am 216 Am_65
## [37] NR_004394 47 + | Am 226 Am_47
## [38] NR_004394 53 + | Am 227 Am_53
## [39] NR_004394 53 + | Am 228 Am_53
## -------
## seqinfo: 9 sequences from hg38 genome; no seqlengths
##
## ...
## <4 more elements>
Since epitranscriptomic modifications by their nature can have different meaning for each of the individual transcript variants. This also introduces conflicts for saving epitranscriptomics coordinates. In the example above the coordinates are given per transcript, because of the source data.
However, not all sources report transcript coordinates. It might be of interest to shift the coordinates to transcript coordinates and at the same time taking care that with transcript variants multiple options exist for each of the transcript maturation process: From one genomic coordinate, multiple transcriptomic coordinates can be spawned.
Whether this is biologically relevant or whether biological evidence does exist for each modification on each transcript cannot be guaranteed or differentiated technically depending on the methods used. This might change with the arrival of new techniques allowing for detection of modified nucleotides per individual transcript variant.
txdb <- TxDb.Hsapiens.UCSC.hg38.knownGene
seqlevels(txdb) <- "chr1"
bs <- BSgenome.Hsapiens.UCSC.hg38
etdb <- EpiTxDb.Hs.hg38.RMBase()
## downloading 1 resources
## retrieving 1 resource
## loading from cache
## [1] 47275
In the following example we will focus on shifting the coordinates to
individual mature transcripts. However, keep in mind, that premature
transcript might be of interest as well and this can be controlled via
the tx
arguments of
shiftGenomicToTranscript()
## Warning: Coordinates for 974 ranges of 'subject' not found:
## 'chr1:14662:-','chr1:14668:-','chr1:139005:-','chr1:139020:-','chr1:139040:-','chr1:139127:-','chr1:629454:+','chr1:629456:+','chr1:629465:+','chr1:629595:+'
## and more ...
## [1] 201525
Due to multiple matches for each transcript variant the number of modifications has increased.
With the we can plot the relative positions of modifications by type
on chr1
transcripts.
mod_tx <- split(mod_tx,seqnames(mod_tx))
names <- Reduce(intersect,list(names(mod_tx),names(tx)))
# Getting the corresponding 5'-UTR and 3'-UTR annotations
fp <- fiveUTRsByTranscript(txdb)
tp <- threeUTRsByTranscript(txdb)
tx <- tx[names]
mod_tx <- mod_tx[names]
fp_m <- match(names,names(fp))
fp_m <- fp_m[!is.na(fp_m)]
tp_m <- match(names,names(tp))
tp_m <- tp_m[!is.na(tp_m)]
fp <- fp[fp_m]
tp <- tp[tp_m]
# Getting lengths of transcripts, 5'-UTR and 3'-UTR
tx_lengths <- sum(width(tx))
fp_lengths <- rep(0L,length(tx))
names(fp_lengths) <- names
fp_lengths[names(fp)] <- sum(width(fp))
tp_lengths <- rep(0L,length(tx))
names(tp_lengths) <- names
tp_lengths[names(tp)] <- sum(width(tp))
# Rescale modifications
# CDS start is at position 1L and cds end at position 1000L
from <- IRanges(fp_lengths+1L, tx_lengths - tp_lengths)
to <- IRanges(1L,1000L)
mod_rescale <- rescale(mod_tx, to, from)
# Construct result data.frame
rel_pos <- data.frame(mod_type = unlist(mcols(mod_rescale,level="within")[,"mod_type"]),
rel_pos = unlist(start(mod_rescale)))
rel_pos <- rel_pos[rel_pos$rel_pos < 1500 & rel_pos$rel_pos > -500,]
## R version 4.4.1 (2024-06-14)
## Platform: x86_64-pc-linux-gnu
## Running under: Ubuntu 24.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.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=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: Etc/UTC
## tzcode source: system (glibc)
##
## attached base packages:
## [1] stats4 stats graphics grDevices utils datasets methods
## [8] base
##
## other attached packages:
## [1] ggplot2_3.5.1
## [2] BSgenome.Hsapiens.UCSC.hg38_1.4.5
## [3] BSgenome_1.75.0
## [4] rtracklayer_1.65.0
## [5] BiocIO_1.17.0
## [6] TxDb.Hsapiens.UCSC.hg38.knownGene_3.20.0
## [7] GenomicFeatures_1.57.1
## [8] EpiTxDb.Hs.hg38_0.99.7
## [9] AnnotationHub_3.15.0
## [10] BiocFileCache_2.15.0
## [11] dbplyr_2.5.0
## [12] EpiTxDb_1.19.0
## [13] Modstrings_1.21.0
## [14] Biostrings_2.75.0
## [15] XVector_0.45.0
## [16] AnnotationDbi_1.69.0
## [17] Biobase_2.67.0
## [18] GenomicRanges_1.57.2
## [19] GenomeInfoDb_1.41.2
## [20] IRanges_2.39.2
## [21] S4Vectors_0.43.2
## [22] BiocGenerics_0.53.0
## [23] BiocStyle_2.35.0
##
## loaded via a namespace (and not attached):
## [1] DBI_1.2.3 bitops_1.0-9
## [3] httr2_1.0.5 tRNAdbImport_1.23.0
## [5] biomaRt_2.63.0 rlang_1.1.4
## [7] magrittr_2.0.3 matrixStats_1.4.1
## [9] compiler_4.4.1 RSQLite_2.3.7
## [11] png_0.1-8 vctrs_0.6.5
## [13] txdbmaker_1.1.2 stringr_1.5.1
## [15] pkgconfig_2.0.3 crayon_1.5.3
## [17] fastmap_1.2.0 labeling_0.4.3
## [19] utf8_1.2.4 Rsamtools_2.21.2
## [21] rmarkdown_2.28 UCSC.utils_1.1.0
## [23] purrr_1.0.2 bit_4.5.0
## [25] xfun_0.48 zlibbioc_1.51.2
## [27] cachem_1.1.0 Structstrings_1.21.0
## [29] jsonlite_1.8.9 progress_1.2.3
## [31] blob_1.2.4 highr_0.11
## [33] DelayedArray_0.31.14 BiocParallel_1.41.0
## [35] parallel_4.4.1 prettyunits_1.2.0
## [37] R6_2.5.1 bslib_0.8.0
## [39] stringi_1.8.4 jquerylib_0.1.4
## [41] SummarizedExperiment_1.35.5 knitr_1.48
## [43] Matrix_1.7-1 tidyselect_1.2.1
## [45] abind_1.4-8 yaml_2.3.10
## [47] codetools_0.2-20 curl_5.2.3
## [49] tRNA_1.23.0 lattice_0.22-6
## [51] tibble_3.2.1 withr_3.0.2
## [53] KEGGREST_1.45.1 evaluate_1.0.1
## [55] xml2_1.3.6 pillar_1.9.0
## [57] BiocManager_1.30.25 filelock_1.0.3
## [59] MatrixGenerics_1.17.1 rex_1.2.1
## [61] generics_0.1.3 RCurl_1.98-1.16
## [63] BiocVersion_3.21.1 hms_1.1.3
## [65] munsell_0.5.1 scales_1.3.0
## [67] glue_1.8.0 maketools_1.3.1
## [69] tools_4.4.1 sys_3.4.3
## [71] GenomicAlignments_1.41.0 buildtools_1.0.0
## [73] XML_3.99-0.17 grid_4.4.1
## [75] colorspace_2.1-1 GenomeInfoDbData_1.2.13
## [77] restfulr_0.0.15 cli_3.6.3
## [79] rappdirs_0.3.3 fansi_1.0.6
## [81] S4Arrays_1.5.11 dplyr_1.1.4
## [83] gtable_0.3.6 sass_0.4.9
## [85] digest_0.6.37 SparseArray_1.5.45
## [87] farver_2.1.2 rjson_0.2.23
## [89] memoise_2.0.1 htmltools_0.5.8.1
## [91] lifecycle_1.0.4 httr_1.4.7
## [93] mime_0.12 bit64_4.5.2