https://github.com/bionetslab/ppi-splitting-pipeline
Automated leakage-aware splitting of a given PPI dataset into train, validation, and test set
https://github.com/bionetslab/ppi-splitting-pipeline
Last synced: 23 days ago
JSON representation
Automated leakage-aware splitting of a given PPI dataset into train, validation, and test set
- Host: GitHub
- URL: https://github.com/bionetslab/ppi-splitting-pipeline
- Owner: bionetslab
- License: mit
- Created: 2026-06-19T08:22:37.000Z (about 1 month ago)
- Default Branch: main
- Last Pushed: 2026-07-01T10:04:57.000Z (28 days ago)
- Last Synced: 2026-07-01T12:07:47.639Z (27 days ago)
- Language: Python
- Size: 522 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 6
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# PPI Splitting Pipeline
Automated leakage-aware splitting of a protein–protein interaction (PPI) dataset into train, validation, and test sets, with redundancy removal, negative sampling, embedding-based classification, and bias analysis.
## Quick Start
### 1. Install dependencies
```bash
conda env create -f environment.yml
conda activate ppi-splitting-pipeline
```
### 2. Prepare your input
Create a CSV file with at least two columns (`protein1`, `protein2`) containing UniProt accession IDs. Additional columns (e.g. STRING evidence scores) are preserved throughout the pipeline.
```
protein1,protein2
P45985,Q14315
Q86TC9,P35609
O14836-2,P12345
...
```
### 3. Run the pipeline
```bash
nextflow run main.nf --ppis ppis.csv --outdir results
```
If you have a GPU, additionally specify `-profile gpu`, which will submit only the embedding steps to the GPU:
```bash
nextflow run main.nf --ppis ppis.csv --outdir results -profile gpu -c my_config.config
```
Config example for an HPC with slurm and a dedicated GPU queue: https://nf-co.re/configs/daisybio/. Important part:
```bash
profiles {
...
gpu {
docker.runOptions = '-u $(id -u):$(id -g) --gpus all'
apptainer.runOptions = '--nv'
singularity.runOptions = '--nv'
process{
withLabel:process_gpu {
queue = 'shared-gpu'
clusterOptions = '--qos=limitgpus --gpus=a40:1 --exclude compms-gpu-1.exbio.wzw.tum.de'
}
}
}
}
}
```
Key parameters (all optional):
| Parameter | Default | Description |
|---|---|---|
| `--ppis` | `ppis.csv` | Input PPI CSV file |
| `--outdir` | `results` | Output directory |
| `--embedding_model` | `esm2` | Embedding model: `none` (one-hot), `esm2`, `prot_t5`, or path to a pre-computed `.npz` file |
| `--edge_weight` | `normalized_bitscore` | BLAST edge weight for the similarity graph: `bitscore` or `normalized_bitscore` |
| `--kahip_k` | `3` | Number of partitions (train / val / test) |
| `--kahip_seed` | `1234` | KaHIP random seed |
| `--kahip_preconfiguration` | `strong` | KaHIP mode: `strong`, `eco`, `fast`, `ultrafast` |
| `--cdhit_identity` | `0.4` | CD-HIT sequence identity threshold for redundancy removal |
| `--seed` | `42` | Random seed for negative sampling, classification, and bias analysis |
Example with custom parameters:
```bash
nextflow run main.nf \
--ppis string900_ppis.csv \
--outdir results/string900 \
--embedding_model prot_t5 \
--kahip_k 3
```
### 4. View the report
Open `results/multiqc/multiqc_report.html` in a browser.
---
## Workflow

```
ppis.csv
│
├─ FETCH_DATA ──────────────────────────────────── sequences.fasta
│ │ go_annotations.tsv
│ │ species.tsv
│ │
├─ GET_LENGTHS ──────────────────────────────────── lengths.tsv
│
├─ RUN_BLAST ────────────────────────────────────── all_vs_all.tsv
│
├─ MAKE_METIS ───────────────────────────────────── similarity.graph
│ node_mapping.tsv
├─ RUN_KAHIP ────────────────────────────────────── partitioned_proteome.txt
│
├─ SORT_PPIS ────────────────────────────────────── train/val/test .csv + .fasta
│
├─ CDHIT (train↔val, train↔test)
│
├─ REMOVE_REDUNDANT ─────────────────────────────── train_nr/val_nr/test_nr .csv + .fasta
│
├─ SAMPLE_NEGATIVES ─────────────────────────────── train/val/test_balanced/test_realistic .csv
│
├─ EMBED_SEQUENCES ──────────────────────────────── embeddings.npz
│
├─ TRAIN_CLASSIFIER ─────────────────────────────── classifier_metrics_mqc.tsv
│
├─ BIAS_ANALYSIS (×6–7 attributes, parallel) ────── *_bias_mqc.tsv
│
├─ COLLECT_BIAS ─────────────────────────────────── bias_scatter_mqc.html
│
├─ SIMILARITY_HEATMAP ───────────────────────────── similarity_heatmap_mqc.html
│
└─ MULTIQC ──────────────────────────────────────── multiqc_report.html
```
### Step descriptions
**FETCH_DATA** — Queries UniProt for all proteins in the input CSV. Retrieves sequences (canonical + isoform-specific via the FASTA endpoint), GO annotations (biological process, molecular function, cellular component), and NCBI taxon IDs. Outputs `sequences.fasta`, `go_annotations.tsv`, and `species.tsv`.
**GET_LENGTHS** — Computes per-protein sequence lengths for length-normalised BLAST scores.
**RUN_BLAST** — Runs all-against-all BLASTp with `makeblastdb` + `blastp` to quantify pairwise sequence similarity.
**MAKE_METIS** — Converts the BLAST results into a weighted similarity graph in METIS format. Edge weights are either raw bitscore or bitscore normalised by the geometric mean of protein lengths.
**RUN_KAHIP** — Partitions the similarity graph into `k` parts using KaHIP's `kaffpa`. Proteins within the same partition are kept together; cross-partition PPIs are discarded. The largest partition becomes train, the second largest val, the smallest test.
**SORT_PPIS** — Assigns each PPI to a split based on the KaHIP partition. Writes per-split CSV and FASTA files.
**CDHIT** — Runs CD-HIT-2D between train↔val and train↔test to identify cross-split similar sequences.
**REMOVE_REDUNDANT** — Removes proteins from val and test that are too similar to any training protein (above the CD-HIT identity threshold).
**SAMPLE_NEGATIVES** — Samples random negative pairs for each split. Negatives are drawn such that each protein's degree distribution is approximately preserved. Produces a balanced test set (1:1 positive:negative) and a realistic test set (1:10 ratio).
**EMBED_SEQUENCES** — Computes per-protein embeddings using the selected model:
- `none` — 21-dimensional mean-pooled one-hot amino acid composition
- `esm2` — ESM-2 650M (dimension 1280), mean-pooled over residues
- `prot_t5` — ProtT5-XL (dimension 1024), mean-pooled over residues
- A path to a pre-computed `.npz` file skips this step entirely.
**TRAIN_CLASSIFIER** — Trains a Random Forest classifier on concatenated pair embeddings. Hyperparameters are tuned on the validation AUROC over 3 configurations (max_depth 5/10/30, max_samples 0.2), then the best model is retrained on train+val and evaluated on the balanced and realistic test sets.
**BIAS_ANALYSIS** — Runs in parallel for each attribute, computing:
- *Utility* — NMI(A; Y) = MI / √(H(A)·H(Y)): how much the attribute is correlated with the PPI label
- *Detectability* — Spearman ρ of a Ridge regressor predicting the attribute from pair embeddings
Attributes analysed:
| Attribute | Description |
|---|---|
| `sequence_similarity` | BLASTp pident between the two proteins, normalised to [0, 1] |
| `embedding_similarity` | Cosine similarity of the two individual protein embeddings |
| `functional_relatedness_BP/MF/CC` | Jaccard similarity of GO term sets (biological process / molecular function / cellular component) |
| `self_interactions` | 1 if both proteins are identical, 0 otherwise |
| `same_species` | 1 if both proteins share the same NCBI taxon ID, 0 otherwise (only included if the dataset contains proteins from more than one species) |
**COLLECT_BIAS** — Aggregates all per-attribute TSVs into a single interactive Plotly scatter plot (NMI vs detectability, coloured by attribute, shaped by split).
**SIMILARITY_HEATMAP** — Plots a heatmap of pairwise BLASTp similarity between proteins in different splits, to visualise the degree of leakage.
**MULTIQC** — Collects all `*_mqc.tsv` and `*_mqc.html` files into a single MultiQC report.
---
## Outputs
```
results/
├── multiqc/
│ └── multiqc_report.html # Main report
├── data/
│ └── embeddings.npz # Pre-computed embeddings (reusable)
├── train.csv # Final labelled splits (positives + negatives)
├── val.csv
├── test_balanced.csv
└── test_realistic.csv
```
---
## Standalone STRING channel analysis
To investigate which STRING evidence channels explain classifier performance differences between datasets, use the standalone script (not part of the Nextflow pipeline):
```bash
python bin/analyse_string_channels.py \
--train results/train.csv \
--test results/test_balanced.csv \
--embeddings results/data/embeddings.npz \
--out string_channel_analysis.tsv
```
This fits a Ridge regressor (on positive pairs only) to predict each STRING evidence channel score from pair embeddings, and reports train and test Spearman ρ per channel. `combined_score` is excluded since it is derived from the individual channels.
---
## Requirements
- [Nextflow](https://www.nextflow.io/) ≥ 23.10
- Conda (for the environment) — or install the packages in `environment.yml` manually
- Internet access for the initial UniProt fetch (subsequent runs use cached Nextflow work directories)
- A GPU is recommended but not required for `esm2` and `prot_t5` embedding models