Deep generalizable prediction of RNA secondary structure via base pair motif energy
Heqin Zhu
·
Fenghe Tang
·
Quan Quan
·
Ke Chen
·
Peng Xiong*
·
S. Kevin Zhou*
Paper |
PDF |
poster |
GitHub |
PyPI
* [Introduction](#introduction)
* [Installation](#installation)
* [Requirements](#requirements)
* [Use base pair motif library](#use-base-pair-motif-library)
* [Predict RNA secondary structure](#predict-rna-secondary-structure)
* [Usage](#usage)
* [Base pair motif library](#base-pair-motif-library)
* [BPfold for secondary structure prediction](#bpfold-for-secondary-structure-prediction)
* [Run command line](#run-command-line)
* [Import python code](#import-python-code)
* [Evaluation](#evaluation)
* [Reproduction](#reproduction)
* [Acknowledgement](#acknowledgement)
* [LICENSE](#license)
* [Citation](#citation)
## Introduction
Deep learning methods have demonstrated great performance for RNA secondary structure prediction. However, generalizability is a common unsolved issue on unseen out-of-distribution RNA families, which hinders further improvement of the accuracy and robustness of deep learning methods. Here we construct a base pair motif library that enumerates the complete space of locally adjacent three-neighbor base pair and records the thermodynamic energy of corresponding base pair motifs through _de novo_ modeling of tertiary structures, and we further develop a deep learning approach for RNA secondary structure prediction, named BPfold, which learns relationship between RNA sequence and the energy map of base pair motif. Experiments on sequence-wise and family-wise datasets have demonstrated the great superiority of BPfold compared to other state-of-the-art approaches in accuracy and generalizability. We hope this work contributes to integrating physical priors and deep learning methods for the further discovery of RNA structures and functionalities.
## Installation
### Requirements
- python3.8+
- anaconda
### Use base pair motif library
```shell
pip3 install BPfold
```
### Predict RNA secondary structure
0. Clone this repo
```shell
git clone git@github.com:heqin-zhu/BPfold.git
# git clone https://github.com/heqin-zhu/BPfold.git
cd BPfold
```
1. Create and activate BPfold environment.
```shell
conda env create -f BPfold_environment.yaml
conda activate BPfold
```
2. Download [model_predict.tar.gz](https://github.com/heqin-zhu/BPfold/releases/latest/download/model_predict.tar.gz) in [releases](https://github.com/heqin-zhu/BPfold/releases) and decompress it.
```shell
wget https://github.com/heqin-zhu/BPfold/releases/latest/download/model_predict.tar.gz
tar -xzf model_predict.tar.gz
```
3. Optional (for training and evaluation): Download datasets [BPfold_data.tar.gz](https://github.com/heqin-zhu/BPfold/releases/latest/download/BPfold_data.tar.gz) in [releases](https://github.com/heqin-zhu/BPfold/releases) and decompress them.
```shell
wget https://github.com/heqin-zhu/BPfold/releases/latest/download/BPfold_data.tar.gz
tar -xzf BPfold_data.tar.gz
```
## Usage
### Base pair motif library
The base pair motif library is publicly available in [releases](https://github.com/heqin-zhu/BPfold/releases), which contains the `motif`:`energy` pairs. The motif is represented as `sequence`\_`pairIdx`\_`pairIdx`\-`chainBreak` where pairIdx is 0-indexed, and the energy is a reference score of statistical and physical thermodynamic energy.
For instance, `CAAAAUG_0_6-3 -49.7835` represents motif `CAAAAUG` has a known pair `C-G` whose indexes are `0` and `6`, with chainBreak lying at position `3`.
>[!NOTE]
>The base pair motif library can be used as thermodynamic priors in other models.
For an input RNA sequence `seq`, the base pair motif energy matrix `mat` can be directly obatined as follows:
```python3
from BPfold.util.base_pair_motif import BPM_energy
BPM = BPM_energy()
seq = 'AUGCGUAGTa'
# default, recommended, normed according to the major energy of each motif type, BPfold used, shape 2xLxL
mat = BPM.get_energy(seq)
# origin energy, value may be -50.3, 49.7, ..., shape 1xLxL
mat2 = BPM.get_energy(seq, normalize_energy=False, dispart_outer_inner=False)
```
To get a folding score of a sequence for reference, we accumulate all energy items from canonical base pairs assigned by greedy search matching algorithm (issue #2).
```python
from src.BPfold.util.base_pair_motif import BPM_energy()
seq = 'GCGCAGGACUCGGCUUCUUCGGAAGGGACGAGGGGCGC'
score = BPM_energy().get_score(seq)
print(score)
```
### BPfold for secondary structure prediction
#### Run command line
Args:
- `--checkpoint_dir`: required, specify checkpoint dir path.
- `--seq`: specify one or more input RNA sequences.
- `--input`: specify input file of RNA seqs in format of `.fasta`(multiple seqs are supported), `.bpseq`, `.ct`, or `.dbn`.
- `--output`: output dir (will be created automatically), default `BPfold_results`.
- `--out_type`: out format of RNA secondary structures, can be `csv`, `bpseq`, `ct`, or `dbn`, default `csv`
Here are some examples:
```shell
BPfold --checkpoint_dir PATH_TO_CHECKPOINT_DIR --seq GGUAAAACAGCCUGU AGUAGGAUGUAUAUG --output BPfold_results
BPfold --checkpoint_dir PATH_TO_CHECKPOINT_DIR --input examples/examples.fasta --out_type csv # (multiple sequences are supported)
BPfold --checkpoint_dir PATH_TO_CHECKPOINT_DIR --input examples/URS0000D6831E_12908_1-117.bpseq
```
Example of BPfold prediction
Here are the outputs after running `BPfold --checkpoint_dir model_predict --input examples/examples.fasta --out_type bpseq`:
```txt
>> Welcome to use "BPfold" for predicting RNA secondary structure!
Loading model_predict/BPfold_1-6.pth
Loading model_predict/BPfold_2-6.pth
Loading model_predict/BPfold_3-6.pth
Loading model_predict/BPfold_4-6.pth
Loading model_predict/BPfold_5-6.pth
Loading model_predict/BPfold_6-6.pth
[ 1] saved in "BPfold_results/1M5L.bpseq", CI=0.913
GCGCAGGACUCGGCUUCUUCGGAAGGGACGAGGGGCGC
((((....((((.(((((..)))))...))))..))))
............(..............).......... NC
((((....((((((((((..)))))..)))))..)))) MIX
[ 2] saved in "BPfold_results/URS0000D6831E_12908_1-117.bpseq", CI=0.892
UUAUCUCAUCAUGAGCGGUUUCUCUCACAAACCCGCCAACCGAGCCUAAAAGCCACGGUGGUCAGUUCCGCUAAAAGGAAUGAUGUGCCUUUUAUUAGGAAAAAGUGGAACCGCCUG
......((((((.....((((.......))))..(((.((((.((......))..))))))).................))))))..(((......)))..................
..................................................................................................................... NC
......((((((.....((((.......))))..(((.((((.((......))..))))))).................))))))..(((......))).................. MIX
Confidence indexes are saved in "BPfold_results_confidence_20250915_03h19m33s.yaml"
Program Finished!
```
>[!NOTE]
>Results (dbn, connects, bpseq...) with no tag are predicted canonical pairs, tagged with `_nc` are predicted non-canonical pairs, and tagged with `_mix` are mixed canonical and non-canonical pairs (i.e., all base pairs). If you want to ignore non-canonical pairs, pass argument `--ignore_nc` to BPfold.
Run command `BPfold -h` for more help information.
#### Import python code
Specify arguments:
- `checkpiont_dir`
- at least one of `input_seqs` (list of seqs) and `input_path` (fasta\_path)
```python
from BPfold.predict import BPfold_predict
from BPfold.util.RNA_kit import connects2dbn
## arguments
checkpoint_dir = '' # to be specified
input_seqs = ['GCGCAGGACUCGGCUUCUUCGGAAGGGACGAGGGGCGC', 'AUGUAUGUCCUGUCGUA']
input_path = 'examples/examples.fasta'
## init model
BPfold_predictor = BPfold_predict(checkpoint_dir)
## BPfold predict # specify at least one of input_seqs and input_path
pred_results = BPfold_predictor.predict(input_seqs=input_seqs, input_path=input_path, ignore_nc=False)
for dic in pred_results:
print(f'>{dic["seq_name"]}')
print(dic["seq"])
print(connects2dbn(dic["connects"]), f'CI={dic["CI"]:.3f}')
```
Results of BPfold prediction
```txt
Loading /public2/home/heqinzhu/gitrepo/RNA/SS_pred/BPfold/src/BPfold/paras/model_predict/BPfold_1-6.pth
Loading /public2/home/heqinzhu/gitrepo/RNA/SS_pred/BPfold/src/BPfold/paras/model_predict/BPfold_2-6.pth
Loading /public2/home/heqinzhu/gitrepo/RNA/SS_pred/BPfold/src/BPfold/paras/model_predict/BPfold_3-6.pth
Loading /public2/home/heqinzhu/gitrepo/RNA/SS_pred/BPfold/src/BPfold/paras/model_predict/BPfold_4-6.pth
Loading /public2/home/heqinzhu/gitrepo/RNA/SS_pred/BPfold/src/BPfold/paras/model_predict/BPfold_5-6.pth
Loading /public2/home/heqinzhu/gitrepo/RNA/SS_pred/BPfold/src/BPfold/paras/model_predict/BPfold_6-6.pth
>seq_20250929_14h23m28s_1
GCGCAGGACUCGGCUUCUUCGGAAGGGACGAGGGGCGC
((((....((((.(((((..)))))...))))..)))) CI=0.913
>seq_20250929_14h23m28s_2
AUGUAUGUCCUGUCGUA
.....((......)).. CI=0.807
>1M5L
GCGCAGGACUCGGCUUCUUCGGAAGGGACGAGGGGCGC
((((....((((.(((((..)))))...))))..)))) CI=0.913
>URS0000D6831E_12908_1-117
UUAUCUCAUCAUGAGCGGUUUCUCUCACAAACCCGCCAACCGAGCCUAAAAGCCACGGUGGUCAGUUCCGCUAAAAGGAAUGAUGUGCCUUUUAUUAGGAAAAAGUGGAACCGCCUG
......((((((.....((((.......))))..(((.((((.((......))..))))))).................))))))..(((......))).................. CI=0.892
```
### Evaluation
Specify `pred_dir` and `gt_dir`. In each directory, there are secondary structures in format of `bpseq`, `ct`, or `dbn`.
```shell
BPfold_eval --pred_dir BPfold_results --gt_dir PATH_TO_NATIVE_STRUCTURES
```
## Reproduction
For reproduction of all the quantitative results, we provide the predicted secondary structures and model parameters of BPfold in experiments. You can **directly downalod** the predicted secondary structures by BPfold *or* **use BPfold v0.2.0** with trained parameters to predict these secondary structures, and then **evaluate** the predicted results.
**Directly download**
```shell
wget https://github.com/heqin-zhu/BPfold/releases/download/v0.2/BPfold_test_results.tar.gz
tar -xzf BPfold_test_results.tar.gz
```
**Use BPfold**
1. Download the checkpoints of BPfold: [BPfold_reproduce.tar.gz](https://github.com/heqin-zhu/BPfold/releases/download/v0.2/model_reproduce.tar.gz).
```shell
wget https://github.com/heqin-zhu/BPfold/releases/download/v0.2/model_reproduce.tar.gz
tar -xzf model_reproduce.tar.gz
```
2. Install BPfold version 0.2.4.
```shell
pip install BPfold==0.2.4
```
3. Use BPfold to predict RNA sequences in test datasets.
**Evaluate**
```shell
BPfold_eval --gt_dir BPfold_data --pred_dir BPfold_test_results
```
After running above commands for evaluation, you will see the following outputs:
Outputs of evaluating BPfold
```txt
Time used: 29s
[Summary] eval_BPfold_test_results.yaml
Pred/Total num: [('PDB_test', 116, 116), ('Rfam12.3-14.10', 10791, 10791), ('archiveII', 3966, 3966), ('bpRNA', 1305, 1305), ('bpRNAnew', 5401, 5401)]
-------------------------len>600-------------------------
dataset & num & INF & F1 & P & R \\
Rfam12.3-14.10 & 64 & 0.395 & 0.387 & 0.471 & 0.333\\
archiveII & 55 & 0.352 & 0.311 & 0.580 & 0.242\\
------------------------len<=600-------------------------
dataset & num & INF & F1 & P & R \\
PDB_test & 116 & 0.817 & 0.814 & 0.840 & 0.801\\
Rfam12.3-14.10 & 10727 & 0.696 & 0.690 & 0.662 & 0.743\\
archiveII & 3911 & 0.829 & 0.827 & 0.821 & 0.843\\
bpRNA & 1305 & 0.670 & 0.658 & 0.599 & 0.770\\
bpRNAnew & 5401 & 0.655 & 0.647 & 0.604 & 0.723\\
---------------------------all---------------------------
dataset & num & INF & F1 & P & R \\
PDB_test & 116 & 0.817 & 0.814 & 0.840 & 0.801\\
Rfam12.3-14.10 & 10791 & 0.694 & 0.689 & 0.660 & 0.741\\
archiveII & 3966 & 0.823 & 0.820 & 0.818 & 0.834\\
bpRNA & 1305 & 0.670 & 0.658 & 0.599 & 0.770\\
bpRNAnew & 5401 & 0.655 & 0.647 & 0.604 & 0.723\\
```
## Acknowledgement
We appreciate the following open source projects:
- [UFold](https://github.com/uci-cbcl/UFold)
- [vigg_ribonanza](https://github.com/autosome-ru/vigg_ribonanza/)
- [e2efold](https://github.com/ml4bio/e2efold)
## LICENSE
[MIT LICENSE](LICENSE)
## Citation
If you find our work helpful, please cite our paper:
```bibtex
@article{BPfold,
title = {Deep generalizable prediction of {RNA} secondary structure via base pair motif energy},
author = {Zhu, Heqin and Tang, Fenghe and Quan, Quan and Chen, Ke and Xiong, Peng and Zhou, S. Kevin},
volume = {16},
issn = {2041-1723},
url = {https://doi.org/10.1038/s41467-025-60048-1},
doi = {10.1038/s41467-025-60048-1},
number = {1},
journal = {Nature Communications},
month = jul,
year = {2025},
pages = {5856},
}
```