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}, } ```