--- title: "Introduction to RBPSpecificity" author: "Soon Yi" date: "`r Sys.Date()`" output: BiocStyle::html_document: toc: true toc_depth: 2 vignette: > %\VignetteIndexEntry{Introduction to RBPSpecificity} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include=FALSE} knitr::opts_chunk$set( echo = TRUE, collapse = TRUE, comment = "#>", fig.width = 7, fig.height = 5, warning = FALSE, message = FALSE ) ``` # Overview **RBPSpecificity** provides tools to analyze RNA-Binding Protein (RBP) binding specificities from high-throughput sequencing data. This package provides tools for: - Calculating **Specificity** from k-mer enrichment data - Calculating **Sensitivity** for top motifs - Visualizing specificity distributions and sensitivity profiles - Computing enrichment scores from CLIP peak data # Introduction ## Background The package implements two key metrics for characterizing RBP binding behavior: 1. **Specificity**: Quantifies how specifically an RBP binds its top motif relative to all other motifs. Higher specificity indicates more specific binding. 2. **Sensitivity**: Measures how much the binding affinity changes upon single nucleotide variations in the motif. Higher sensitivity indicates greater sensitivity to sequence changes. These metrics enable quantitative comparison of RBP binding properties across different experimental conditions or between different RBPs. ## Reference 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 ## Workflow Integration **RBPSpecificity** is designed to seamlessly integrate into standard Bioconductor sequence and genomic analysis workflows: - **Input Integration**: Raw peak files from CLIP-seq or similar experiments can be imported as `GRanges` objects using `rtracklayer::import()` and standard annotation packages (e.g. `GenomicFeatures`). - **Sequence Retrieval**: The `motifEnrichment()` function interfaces directly with `BSgenome` genome packages (e.g., `BSgenome.Hsapiens.UCSC.hg38`) to extract genomic sequences for enrichment calculations. - **Downstream Analysis**: The Specificity and Sensitivity scores and matrices returned by the package can be integrated with other downstream analyses such as differential binding studies (e.g., `DiffBind`, `DESeq2`), regulatory network modeling, or motif annotation pipelines. ## Sample Data The sample data included in this package were obtained from the ENCODE portal. ### RBNS Data 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 Data 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. ## Setup ```{r install, eval=FALSE} if (!requireNamespace("BiocManager", quietly = TRUE)) { install.packages("BiocManager") } BiocManager::install("RBPSpecificity") ``` ```{r load-package} library(RBPSpecificity) library(ggplot2) ``` # In Vitro Specificity from Pre-computed Enrichment Data (RBNS) This workflow demonstrates how to calculate specificity and sensitivity from pre-computed enrichment scores, such as those from RBNS (RNA Bind-n-Seq) experiments. ## Loading RBNS Data The sample data contains normalized 5-mer enrichment scores for four RBPs: HNRNPC, PCBP2 (structural context independent), RBFOX2, and EIF4G2 (structural context dependent). ```{r load-rbns} # 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) ``` ## Calculating Specificity and Sensitivity for All Four RBPs The package expects a data.frame with `MOTIF` and `Score` columns: ```{r calc-rbns-metrics} 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) ``` ## Visualization ### Specificity Distribution Plots The `plotSpecificity()` function displays the distribution of k-mer scores, highlighting the top motif and its specificity value: ```{r plot-is-rbns, fig.cap="Distribution of k-mer scores from RBNS data for four RBPs."} plotSpecificity(rbns_metrics[["HNRNPC"]]$enrichment) plotSpecificity(rbns_metrics[["PCBP2"]]$enrichment) plotSpecificity(rbns_metrics[["RBFOX2"]]$enrichment) plotSpecificity(rbns_metrics[["EIF4G2"]]$enrichment) ``` ### Sensitivity Profile Plots The `plotSensitivity()` function visualizes how sensitive binding is to mutations at each position: ```{r plot-vs-rbns, fig.cap="Sensitivity profiles from RBNS data for four RBPs."} plotSensitivity(rbns_metrics[["HNRNPC"]]$enrichment) plotSensitivity(rbns_metrics[["PCBP2"]]$enrichment) plotSensitivity(rbns_metrics[["RBFOX2"]]$enrichment) plotSensitivity(rbns_metrics[["EIF4G2"]]$enrichment) ``` # Cellular Specificity from De Novo Enrichment (eCLIP) 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.hg38` to 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. ## Loading Peak Data ```{r load-eclip, eval = requireNamespace("BSgenome.Hsapiens.UCSC.hg38", quietly = TRUE)} # 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_names ``` ## Running motifEnrichment Pipeline In 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. ```{r run-enrichment, eval = requireNamespace("BSgenome.Hsapiens.UCSC.hg38", quietly = TRUE)} # 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 ) }) 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) ``` ## Visualization The same `plotSpecificity()` and `plotSensitivity()` functions used for RBNS data can be applied to visualize cellular specificity and cellular sensitivity from eCLIP enrichment results: ```{r eclip-plots, eval = requireNamespace("BSgenome.Hsapiens.UCSC.hg38", quietly = TRUE)} # Specificity Distribution plots plotSpecificity(cellular_results[["HNRNPC"]]$enrichment) plotSpecificity(cellular_results[["PCBP2"]]$enrichment) plotSpecificity(cellular_results[["RBFOX2"]]$enrichment) plotSpecificity(cellular_results[["EIF4G2"]]$enrichment) # Sensitivity Profile plots plotSensitivity(cellular_results[["HNRNPC"]]$enrichment) plotSensitivity(cellular_results[["PCBP2"]]$enrichment) plotSensitivity(cellular_results[["RBFOX2"]]$enrichment) plotSensitivity(cellular_results[["EIF4G2"]]$enrichment) ``` # Comparing In Vitro (RBNS) vs. Cellular (eCLIP) Specificity 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. ```{r comparison, eval = requireNamespace("BSgenome.Hsapiens.UCSC.hg38", quietly = TRUE)} 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) ``` # Session Info ```{r session} sessionInfo() ```