--- title: "Introduction to RBPEqBind" author: "Soon Yi" date: "`r Sys.Date()`" output: BiocStyle::html_document: toc: true toc_depth: 2 vignette: > %\VignetteIndexEntry{Introduction to RBPEqBind} %\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 **RBPEqBind** simulates competitive binding of multiple RNA-binding proteins (RBPs) to RNA sequences using an equilibrium binding model. This package provides tools for: - Loading RBP affinity models from k-mer tables - Simulating competitive binding at equilibrium - Visualizing binding profiles and competition patterns - Exporting results to various formats including SummarizedExperiment # Introduction ## Background RBPEqBind implements a mathematical simulation framework for RNA-RBP interactions based on equilibrium binding kinetics. The simulation follows two key principles: 1. **Simultaneous competition**: All RBPs are introduced simultaneously, ensuring equal chances of interaction with the RNA. 2. **Independent binding sites**: Each RNA binding site and its interactions with RBPs are treated as independent events, allowing calculation of equilibrium concentrations for each binding site. ## Motivation Competitive binding among multiple RNA-binding proteins (RBPs) is a fundamental regulator of post-transcriptional gene expression. Understanding how multiple RBPs compete for overlapping binding sites is critical for interpreting transcriptome-wide binding data (such as CLIP-seq) and functional genomics studies. `RBPEqBind` provides a mathematical simulation framework to model competitive RBP binding kinetics on transcript sequences, allowing researchers to explore how RBP binding landscapes are altered by relative protein abundances, RNA concentration, and binding affinity distributions. ## Mathematical Model For an RNA sequence of length $l$ interacting with $N$ RBPs, there exist $l - (k-1)$ possible k-mer binding sites. For each binding site $R$ on the RNA, the kinetic reaction scheme is: $$R + P_i \rightleftharpoons P_iR$$ At equilibrium, the dissociation constant is defined as: $$K_{D,i} = \frac{[R_{eq}][P_{i,eq}]}{[P_iR]}$$ Given the initial concentrations of RBPs ($[P_{0,i}]$) and RNA ($[R_0]$), the equilibrium concentration of each RNA-RBP complex can be determined by solving the system of equations with the constraint: $$[R_0] \geq [R_{eq}] \geq 0$$ From the equilibrium concentrations, binding probability at each unique motif site ($p_{site}$) is calculated as $[P_iR] / [R_{0,e}]$, where $[R_{0,e}] = n \times [R_0]$ is the effective initial RNA concentration accounting for the motif multiplicity $n$ in the transcript sequence. Per-position probability ($p_{pos}$) is then obtained by averaging overlapping $p_{site}$ values across all $k$-mer windows covering each position. For RBP enrichment analysis: - With **a single active RBP**, fold-change (`_occupancy_fc` and `_density_fc`) represents enrichment relative to a uniform distribution across the transcript. - With **multiple active RBPs**, fold-change represents the competitive ratio of self-occupancy relative to the sum of all other active competing RBPs at that position. ## Reference For a detailed description of the mathematical model and its 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 # Installation To install `RBPEqBind`, start R and use the `BiocManager` package: ```r if (!requireNamespace("BiocManager", quietly = TRUE)) install.packages("BiocManager") BiocManager::install("RBPEqBind") ``` For the development version from GitHub, you can use `devtools` or `pak`: ```r # install.packages("devtools") devtools::install_github("S00NYI/RBPEqBind") ``` # Setup ```{r load-packages} library(RBPEqBind) library(data.table) library(ggplot2) ``` # Data Loading ## Loading RBP Models RBP affinity models are loaded from CSV files containing k-mer motifs and scores (enrichment or affinity values). The CSV file requires a column of sequence motifs and score columns for each RBP. The RBP-RNA affinity scores can be derived from: - **RNA Bind-n-Seq** (RBNS) - **RNACompete** - Other similar RBP target enrichment experiments > For generating motif enrichment scores from CLIP experiments, please refer to > the companion R package **RBPSpecificity** (in development). ```{r load-models} # Load raw models from package sample data model_file <- system.file("extdata", "model_RBP.csv", package = "RBPEqBind") raw_models <- loadModel(model_file) # View available RBPs names(raw_models) ``` The included four model RBPs (HH, HL, LH, LL) are designed to bind the 5-mer poly-U motif (UUUUU) with highest affinity, but with varying binding specificity and affinity distributions. For details on how these model RBP scores were generated, please refer to the manuscript referenced above. ## Visualizing Raw Models The `viewModel()` function can be used to inspect the score distributions of raw models before affinity conversion: ```{r view-raw-models, fig.cap="Raw score distributions for model RBPs"} viewModel(raw_models, rbp = c("HH", "HL", "LH", "LL"), bins = 100, alpha = 0.4) ``` ## Setting Affinity Ranges The included RBP models have enrichment scores normalized to a 0-to-1 scale. For binding simulation, each RBP may have different minimum and maximum affinity ranges, which are set using the `setModel()` function: ```{r set-models} # High affinity (H) = high Ka -> low Kd # Low affinity (L) = low Ka -> high Kd max_affinities <- c( "HH" = 100, "HL" = 100, # Ka_max = 100 -> Kd_min = 0.01 nM "LH" = 10, "LL" = 10 # Ka_max = 10 -> Kd_min = 0.1 nM ) min_affinities <- c( "HH" = 0.001, "HL" = 0.001, # Ka_min = 0.001 -> Kd_max = 1000 nM "LH" = 0.001, "LL" = 0.001 ) rbp_models <- setModel(raw_models, max_affinity = max_affinities, min_affinity = min_affinities) ``` The `viewModel()` function can be used again to inspect the converted affinity (Ka) or dissociation constant (Kd) distributions: ```{r view-models-all, fig.cap="Ka distributions for all RBPs"} viewModel(rbp_models, rbp = c("HH", "HL", "LH", "LL"), metric = "Ka", bins = 100, alpha = 0.4) ``` To compare specific RBPs, pass only the desired subset: ```{r view-models-subset, fig.cap="Comparing HH vs LL affinity distributions"} viewModel(rbp_models, rbp = c("HH", "LL"), metric = "Ka", bins = 100, alpha = 0.5) ``` # RNA-RBP Binding Simulations Given the initial concentrations of RBPs and RNA, along with association constants (or dissociation constants) per motif per RBP, RBPEqBind calculates several metrics for each nucleotide position: | Metric | Description | |--------|-------------| | `occupancy` | Binding probability (0-1) | | `density` | Normalized binding (sum = 1) | | `density_fc` | Fold-change over expectation | | `occupancy_fc` | Fold-change over mean occupancy | **For single RBP simulations** (only one RBP with concentration > 0): - `density_fc = density × L` (enrichment over uniform distribution) - `occupancy_fc = occupancy / mean(occupancy)` **For multiple active RBPs**: - `density_fc = self_density / sum(other_densities)` - `occupancy_fc = self_occupancy / sum(other_occupancies)` This vignette covers four simulation scenarios of increasing complexity: 1. **Scenario 1**: Single sequence, fixed concentrations 2. **Scenario 2**: Single sequence, concentration grid sweep 3. **Scenario 3**: FASTA file, fixed concentrations 4. **Scenario 4**: FASTA file, concentration grid sweep # Scenario 1: RBPs Binding to a Single RNA Target at Fixed Concentrations ## Generating or Loading RNA Sequence Users can provide their own sequence or use the built-in `generateRNA()` function to create randomized RNA sequences: ```{r generate-rna} # Generate a random 100-nt RNA sequence random_seq <- generateRNA(100) cat("Generated sequence:", substr(random_seq, 1, 50), "...\n") # Or use a specific reference sequence seq <- "UAGCGGUGCGAUUGGCCCGUGGACCGCGUUUUUGCACUCAUCGUUUCGCACUAAGUACAUAUAGUUGCGACAAAGCCGCUUAUGAGUUGGGGGUAUAUUC" ``` ## Running the Simulation Set initial concentrations of RBPs and target RNA, then run the simulation: ```{r scenario1-simulate} # Define concentrations (nM) - competitive binding of all 4 RBPs prot_concs <- c("HH" = 100, "HL" = 100, "LH" = 100, "LL" = 100) rna_conc <- 10.0 # nM # Detect k-mer size from models k_size <- nchar(rbp_models$HH$motif[1]) # Run simulation res <- simulateBinding( sequence = seq, rbp_models = rbp_models, protein_concs = prot_concs, rna_conc = rna_conc, k = k_size ) # Add transcript column for visualization res$transcript <- "Custom RNA" head(res) ``` ## Visualization Each metric calculated using `simulateBinding()` can be visualized with built-in plotting functions. ### Per-Position Binding Profile The `plotBinding()` function displays binding metrics across positions: > **Note:** The visualizations below show a zoomed-in view from positions 20-60. > The `xlim` parameter can be removed to show the entire sequence, or adjusted > to view a specific segment of the target RNA. ```{r scenario1-binding-raw, fig.cap="Raw density_fc (positions 20-60)"} plotBinding(res, rbp = c("HH", "HL", "LH", "LL"), metric = "density_fc", transcript = "Custom RNA", xlim = c(20, 60)) ``` For smoother visualization, apply a k-mer sliding window average: ```{r scenario1-binding-window, fig.cap="Density FC with 5-mer smoothing window (positions 20-60)"} plotBinding(res, rbp = c("HH", "HL", "LH", "LL"), metric = "density_fc", transcript = "Custom RNA", window = 5, xlim = c(20, 60)) ``` ### Heatmap Visualization The `plotHeatmap()` function displays binding for multiple RBPs simultaneously: ```{r scenario1-heatmap, fig.cap="Heatmap of occupancy_fc (zoomed region)"} plotHeatmap(res, transcript = "Custom RNA", xlim = c(20, 60), xaxis_type = "both", metric = "occupancy_fc") ``` ## Exporting Results Simulation results can be exported using the built-in `exportResults()` function in JSON or CSV format: ```{r scenario1-export} # Export to JSON tmp_json <- tempfile(fileext = ".json") exportResults(res, output_file = tmp_json, format = "json") # Export to CSV tmp_csv <- tempfile(fileext = ".csv") exportResults(res, output_file = tmp_csv, format = "csv") # Clean up unlink(tmp_json) unlink(tmp_csv) ``` Results can also be converted to SummarizedExperiment format: ```{r scenario1-se} se <- makeSE(res, rbp_models = rbp_models) se ``` # Scenario 2: RBP Binding with Varying Concentration Grid To run simulations across multiple combinations of RBP and RNA concentrations, use the `simulateGrid()` function. `RBPEqBind` uses the `future.apply` framework for parallel processing, running sequentially by default and automatically utilizing parallel workers when the user configures a `future::plan`: ```{r scenario2-future-demo, eval = FALSE} # Optional: enable parallel processing across 2 workers library(future) plan(multisession, workers = 2) ``` ## Running Grid Simulation ```{r scenario2-grid} # Define concentration grids prot_grid <- list( HH = c(10, 100), HL = c(10, 100), LH = c(10, 100), LL = c(10, 100) ) rna_grid <- c(10) res_grid <- simulateGrid( sequence = seq, rbp_models = rbp_models, protein_conc_grid = prot_grid, rna_conc_grid = rna_grid, k = k_size ) ``` ## Visualization Grid sweep results can be visualized for specific concentration combinations using the same plotting functions: ```{r scenario2-binding} # Filter to specific concentration combination plotBinding( results = res_grid, rbp = c("HH", "HL", "LH", "LL"), rna_conc = 10, protein_conc = c(HH=10, HL=10, LH=100, LL=100), metric = "density" ) ``` ### Competition Grid Plot The `plotGrid()` function focuses on changes in binding for one RBP across different target RNA and competitor RBP concentrations: ```{r scenario2-plot-grid} # First run a 2-RBP simulation for cleaner visualization rbp_models_2rbp <- rbp_models[c("HH", "LL")] res_grid_2rbp <- simulateGrid( sequence = seq, rbp_models = rbp_models_2rbp, protein_conc_grid = list(HH = c(10, 50), LL = c(10, 50)), rna_conc_grid = c(10), k = k_size ) plotGrid( results = res_grid_2rbp, rbp1 = "HH", rbp2 = "LL", rbp1_concs = c(10, 50), roi_range = c(29, 33), metric = "density" ) ``` Grid sweep results can also be exported in JSON/CSV or SummarizedExperiment format. # Scenario 3: RBPs Binding to Multiple Target RNAs To simulate RBP binding to multiple RNA sequences (e.g., transcript sequences from bioMart), RBPEqBind provides functions to load FASTA files directly. Note that binding simulation is performed on a sequence-by-sequence basis, not simultaneously on all RNA sequences in the FASTA file. ```{r scenario3-simulate} # Load sample FASTA from package fasta_file <- system.file("extdata", "test_transcripts.fa", package = "RBPEqBind") res_fasta <- simulateBindingFasta( fasta_file = fasta_file, rbp_models = rbp_models, protein_concs = c(HH = 100, HL = 100, LH = 100, LL = 100), rna_conc = 10, k = 5 ) head(res_fasta) ``` Visualization and result export are performed the same way as in Scenario 1. # Scenario 4: RBPs Binding to Multiple Target RNAs Across Different Concentrations RBPEqBind also supports concentration grid sweeps across sequences in a FASTA file: ```{r scenario4-grid} fasta_file <- system.file("extdata", "test_transcripts.fa", package = "RBPEqBind") res_grid_fasta <- simulateGridFasta( fasta_file = fasta_file, rbp_models = rbp_models, protein_conc_grid = list( HH = c(10, 100), HL = c(10, 100), LH = c(10, 100), LL = c(10, 100) ), rna_conc_grid = c(10), k = 5 ) head(res_grid_fasta) ``` Visualization and export functions work the same as in Scenario 2. # Session Info ```{r session} sessionInfo() ```