RBPSpecificity provides tools to analyze RNA-Binding Protein (RBP) binding specificities from high-throughput sequencing data. This package provides tools for:
The package implements two key metrics for characterizing RBP binding behavior:
These metrics enable quantitative comparison of RBP binding properties across different experimental conditions or between different RBPs.
For a detailed description of these metrics and their biological applications, please refer to:
Yi S, Singh SS, Ye X, Krishna R, Kothwela V, Jankowsky E, Luna JM. (2025). Inherent Specificity and Mutational Sensitivity as Quantitative Metrics for RBP Binding. bioRxiv. https://www.biorxiv.org/content/10.1101/2025.03.28.646018v4
RBPSpecificity is designed to seamlessly integrate into standard Bioconductor sequence and genomic analysis workflows:
GRanges objects
using rtracklayer::import() and standard annotation
packages (e.g. GenomicFeatures).motifEnrichment() function interfaces directly with
BSgenome genome packages (e.g.,
BSgenome.Hsapiens.UCSC.hg38) to extract genomic sequences
for enrichment calculations.DiffBind, DESeq2), regulatory
network modeling, or motif annotation pipelines.The sample data included in this package were obtained from the ENCODE portal.
RNA Bind-n-Seq (RBNS) datasets provide in vitro RNA-RBP affinity measurements. For each K-mer enrichment dataset, the RBP concentration generating the highest R-value was selected as the representative sample. The collected RBNS R scores were feature-scaled to [1, e] followed by natural log transformation to normalize to a 0-to-1 scale.
eCLIP datasets provide in vivo RBP binding site information. Peak coordinates were extended 25 nucleotides upstream from the 5’-end. Motif enrichment was calculated by counting K-mer appearances across extended peaks and subtracting background counts from randomly shifted genomic regions (up to 500 nt away). Background generation was repeated 100 times for robust averaging.
This workflow demonstrates how to calculate specificity and sensitivity from pre-computed enrichment scores, such as those from RBNS (RNA Bind-n-Seq) experiments.
The sample data contains normalized 5-mer enrichment scores for four RBPs: HNRNPC, PCBP2 (structural context independent), RBFOX2, and EIF4G2 (structural context dependent).
# Load sample RBNS data from package
rbns_file <- system.file("extdata", "RBNS_normalized_5mer.csv",
package = "RBPSpecificity"
)
rbns_data <- read.csv(rbns_file, stringsAsFactors = FALSE)
# Preview the data
head(rbns_data)
#> Motif EIF4G2 HNRNPC RBFOX2 PCBP2
#> 1 AAAAA 0.4667673 0.02115767 0.05019945 0.02791232
#> 2 AAAAC 0.3879612 0.02118148 0.02586520 0.05477091
#> 3 AAAAG 0.4692119 0.01456301 0.05103704 0.01947033
#> 4 AAAAU 0.4591129 0.02351263 0.04702782 0.02892464
#> 5 AAACA 0.3666514 0.02098727 0.02119075 0.02849734
#> 6 AAACC 0.3428551 0.03361433 0.01435467 0.18305568The package expects a data.frame with MOTIF and
Score columns:
rbps <- c("HNRNPC", "PCBP2", "RBFOX2", "EIF4G2")
rbns_metrics <- lapply(rbps, function(rbp) {
rbns_enrichment <- data.frame(
MOTIF = rbns_data$Motif,
Score = rbns_data[[rbp]]
)
is_val <- returnSpecificity(rbns_enrichment)
vs_val <- returnSensitivity(rbns_enrichment, output_type = "number")
list(
enrichment = rbns_enrichment,
Specificity = is_val,
Sensitivity = vs_val
)
})
names(rbns_metrics) <- rbps
# Display in vitro metrics
invitro_summary <- data.frame(
RBP = rbps,
Specificity = sapply(rbns_metrics, function(x) round(x$Specificity, 2)),
Sensitivity = sapply(rbns_metrics, function(x) round(x$Sensitivity, 4))
)
print(invitro_summary)
#> RBP Specificity Sensitivity
#> HNRNPC HNRNPC 50.84 0.8580
#> PCBP2 PCBP2 21.57 0.4932
#> RBFOX2 RBFOX2 31.51 0.9027
#> EIF4G2 EIF4G2 2.04 0.4359The plotSpecificity() function displays the distribution
of k-mer scores, highlighting the top motif and its specificity
value:
Distribution of k-mer scores from RBNS data for four RBPs.
Distribution of k-mer scores from RBNS data for four RBPs.
Distribution of k-mer scores from RBNS data for four RBPs.
Distribution of k-mer scores from RBNS data for four RBPs.
The plotSensitivity() function visualizes how sensitive
binding is to mutations at each position:
Sensitivity profiles from RBNS data for four RBPs.
Sensitivity profiles from RBNS data for four RBPs.
Sensitivity profiles from RBNS data for four RBPs.
Sensitivity profiles from RBNS data for four RBPs.
This workflow demonstrates how to calculate enrichment scores
directly from peak data using the motifEnrichment()
function.
Note: While this example uses eCLIP-derived peaks,
motifEnrichment()works with any peak data in BED format (e.g., iCLIP, PAR-CLIP, or other ChIP-seq derived peaks).
Requirement: This workflow requires
BSgenome.Hsapiens.UCSC.hg38to be installed.
When calculating enrichment from cellular peak data, the resulting metrics are referred to as Cellular Specificity and Cellular Sensitivity, as they reflect in vivo binding behavior rather than intrinsic biochemical affinity.
# Load eCLIP peaks (10-column narrowPeak format) from package
bed_cols <- c(
"chr", "start", "end", "name", "score", "strand",
"signalValue", "pValue", "qValue", "peak"
)
rbp_names <- c("HNRNPC", "PCBP2", "RBFOX2", "EIF4G2")
cell_lines <- c("K562", "HepG2", "K562", "K562")
peak_data <- lapply(seq_along(rbp_names), function(i) {
bed_file <- system.file("extdata",
sprintf("ENCODE_eCLIP_%s_%s_narrowPeak.bed", rbp_names[i], cell_lines[i]),
package = "RBPSpecificity"
)
peaks <- read.table(bed_file, header = FALSE, sep = "\t")
colnames(peaks) <- bed_cols
message("Loaded ", nrow(peaks), " ", rbp_names[i], " peaks.")
peaks
})
names(peak_data) <- rbp_namesIn addition to standard input variables,
motifEnrichment() provides several parameters for
customization:
| Parameter | Description |
|---|---|
extension |
Numeric vector of length 2: c(five_prime, three_prime)
indicating shifting of 5’ and 3’ ends. Positive extends, negative
trims. |
method |
Enrichment model: "anr" (default, any number of
repetitions, conditional Binomial test) or "zoops"
(zero-or-one occurrence per sequence, Hypergeometric test) |
bkg_iter |
Number of background iterations for averaging (higher = more robust) |
bkg_min_dist |
Minimum distance (bp) to shift peaks when generating background regions |
bkg_max_dist |
Maximum distance (bp) for shifting peaks in background generation |
scramble_bkg |
Logical, scramble background sequences to control for nucleotide composition (default: FALSE) |
nucleic_acid_type |
Character string, "DNA" or "RNA" (default:
"DNA") |
ZOOPS method can also be used instead. Note that ANR and ZOOPS
calculation can result in different motif enrichment values and thus
different specificity and sensitivity calculations. For more information
on ANR vs. ZOOPS, please check the GitHub README and Further Reading
section. In addition, the scramble background option can be turned on
(scramble_bkg = TRUE) to control for nucleotide
composition.
# NOTE: This requires BSgenome.Hsapiens.UCSC.hg38
cellular_results <- lapply(rbp_names, function(rbp) {
message("Running motifEnrichment for ", rbp, "...")
enrichment <- motifEnrichment(
coordinates = peak_data[[rbp]],
species_or_build = "hg38",
K = 5,
extension = c(25, 0),
method = "anr",
bkg_iter = 100,
scramble_bkg = FALSE
)
cs_val <- returnSpecificity(enrichment)
cvs_val <- returnSensitivity(enrichment, output_type = "number")
list(
enrichment = enrichment,
Specificity = cs_val,
Sensitivity = cvs_val
)
})
#> | | | 0% | |======================================================================| 100%
#> | | | 0% | |==================== | 28% | |======================================= | 56% | |=========================================================== | 84% | |======================================================================| 100%
#> | | | 0% | |================================================ | 69% | |======================================================================| 100%
#> | | | 0% | |==================================== | 52% | |======================================================================| 100%
names(cellular_results) <- rbp_names
# Display cellular metrics
cellular_summary <- data.frame(
RBP = rbp_names,
Specificity = sapply(cellular_results, function(x) round(x$Specificity, 2)),
Sensitivity = sapply(cellular_results, function(x) round(x$Sensitivity, 4))
)
print(cellular_summary)
#> RBP Specificity Sensitivity
#> HNRNPC HNRNPC 35.28 0.9420
#> PCBP2 PCBP2 6.89 0.6570
#> RBFOX2 RBFOX2 3.00 0.4825
#> EIF4G2 EIF4G2 16.50 0.8937The same plotSpecificity() and
plotSensitivity() functions used for RBNS data can be
applied to visualize cellular specificity and cellular sensitivity from
eCLIP enrichment results:
A key application is comparing specificity and sensitivity across in vitro and cellular contexts. RBPs that bind directly to single-stranded sequence motifs (e.g., HNRNPC, PCBP2) are expected to show correlated specificity and sensitivity values. RBPs whose binding depends on structural context (e.g., RBFOX2, EIF4G2) may show divergence between in vitro and cellular metrics.
comparison <- data.frame(
RBP = rbp_names,
Structural_Context = c("Independent", "Independent", "Dependent", "Dependent"),
In_Vitro_Specificity = sapply(rbns_metrics[rbp_names], function(x) round(x$Specificity, 2)),
Cellular_Specificity = sapply(cellular_results, function(x) round(x$Specificity, 2)),
In_Vitro_Sensitivity = sapply(rbns_metrics[rbp_names], function(x) round(x$Sensitivity, 4)),
Cellular_Sensitivity = sapply(cellular_results, function(x) round(x$Sensitivity, 4))
)
print(comparison)
#> RBP Structural_Context In_Vitro_Specificity Cellular_Specificity
#> HNRNPC HNRNPC Independent 50.84 35.28
#> PCBP2 PCBP2 Independent 21.57 6.89
#> RBFOX2 RBFOX2 Dependent 31.51 3.00
#> EIF4G2 EIF4G2 Dependent 2.04 16.50
#> In_Vitro_Sensitivity Cellular_Sensitivity
#> HNRNPC 0.8580 0.9420
#> PCBP2 0.4932 0.6570
#> RBFOX2 0.9027 0.4825
#> EIF4G2 0.4359 0.8937sessionInfo()
#> R version 4.6.1 (2026-06-24)
#> Platform: x86_64-pc-linux-gnu
#> Running under: Ubuntu 26.04 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] BSgenome.Hsapiens.UCSC.hg38_1.4.5 BSgenome_1.81.0
#> [3] rtracklayer_1.73.0 BiocIO_1.23.3
#> [5] Biostrings_2.81.5 XVector_0.53.0
#> [7] GenomicRanges_1.65.1 GenomeInfoDb_1.49.1
#> [9] Seqinfo_1.3.0 IRanges_2.47.2
#> [11] S4Vectors_0.51.5 BiocGenerics_0.59.10
#> [13] generics_0.1.4 ggplot2_4.0.3
#> [15] RBPSpecificity_0.99.6 BiocStyle_2.41.0
#>
#> loaded via a namespace (and not attached):
#> [1] SummarizedExperiment_1.43.0 gtable_0.3.6
#> [3] rjson_0.2.23 xfun_0.60
#> [5] bslib_0.11.0 Biobase_2.73.1
#> [7] lattice_0.22-9 vctrs_0.7.3
#> [9] tools_4.6.1 bitops_1.0-9
#> [11] curl_7.1.0 parallel_4.6.1
#> [13] BiocBaseUtils_1.15.1 Matrix_1.7-5
#> [15] RColorBrewer_1.1-3 S7_0.2.2
#> [17] cigarillo_1.3.1 lifecycle_1.0.5
#> [19] stringr_1.6.0 compiler_4.6.1
#> [21] farver_2.1.2 Rsamtools_2.29.0
#> [23] codetools_0.2-20 htmltools_0.5.9
#> [25] sys_3.4.3 buildtools_1.0.0
#> [27] sass_0.4.10 RCurl_1.98-1.19
#> [29] yaml_2.3.12 crayon_1.5.3
#> [31] jquerylib_0.1.4 BiocParallel_1.47.0
#> [33] cachem_1.1.0 DelayedArray_0.39.3
#> [35] abind_1.4-8 digest_0.6.39
#> [37] stringi_1.8.7 reshape2_1.4.5
#> [39] restfulr_0.0.17 labeling_0.4.3
#> [41] maketools_1.3.2 fastmap_1.2.0
#> [43] grid_4.6.1 cli_3.6.6
#> [45] SparseArray_1.13.2 magrittr_2.0.5
#> [47] S4Arrays_1.13.0 XML_3.99-0.23
#> [49] withr_3.0.3 UCSC.utils_1.9.0
#> [51] scales_1.4.0 rmarkdown_2.31
#> [53] httr_1.4.8 matrixStats_1.5.0
#> [55] otel_0.2.0 evaluate_1.0.5
#> [57] knitr_1.51 rlang_1.3.0
#> [59] Rcpp_1.1.2 glue_1.8.1
#> [61] BiocManager_1.30.27 jsonlite_2.0.0
#> [63] plyr_1.8.9 R6_2.6.1
#> [65] MatrixGenerics_1.25.0 GenomicAlignments_1.49.1