ML-QSAR Framework for pIC50 Prediction of Replicase Polyprotein Inhibitors
Cheminformatics · QSAR modelling · Random Forest · Streamlit · PubChem fingerprints · ChEMBL
This repository presents an end-to-end machine learning QSAR pipeline for predicting the bioactivity (pIC50) of small molecules against the SARS-CoV-2 Replicase Polyprotein — a validated drug target for COVID-19 therapeutics. The framework retrieves IC50 bioactivity data directly from ChEMBL, performs exploratory chemical space analysis with Lipinski descriptor profiling, computes 881-bit PubChem fingerprints via PaDEL-Descriptor, and trains a Random Forest regression model validated against a held-out 20% test set. Model performance is benchmarked against 40+ scikit-learn regression algorithms using LazyPredict. The trained model is deployed as an interactive Streamlit web application that accepts user-supplied SMILES input and returns predicted pIC50 values with a downloadable CSV output.
- Key Features
- Target Biology
- Pipeline Overview
- Repository Structure
- Data Description
- Bioactivity Classification Thresholds
- Descriptors and Feature Engineering
- Machine Learning Model
- Streamlit Web Application
- Output Files
- Installation and Dependencies
- Usage
- Author
| Feature | Description |
|---|---|
| COVID-19-specific target | Trained on IC50 data for SARS-CoV-2 Replicase Polyprotein from ChEMBL |
| Automated ChEMBL query | IC50 records retrieved via REST API using chembl_webresource_client |
| Activity classification | Active / inactive / intermediate labels based on IC50 thresholds |
| Lipinski EDA | MW, LogP, HBD, HBA computed via RDKit with box plots and scatter plots |
| PubChem fingerprints | 881-bit binary fingerprints via PaDEL-Descriptor |
| Random Forest QSAR model | pIC50 regression with 80/20 train/test split, R² and MSE evaluation |
| LazyPredict benchmarking | Automated comparison of 40+ regression algorithms |
| Streamlit web app | Interactive browser-based tool for predicting pIC50 of novel compounds |
| One-click CSV download | Predictions exportable directly from the web app |
| Serialised model | Trained model saved as COVID19_model.pkl for reuse |
| Property | Detail |
|---|---|
| Target name | Replicase polyprotein 1ab (nsp1–nsp16) |
| Organism | SARS-CoV-2 (COVID-19) |
| Target class | Viral non-structural polyprotein |
| Relevance | The replicase polyprotein is essential for SARS-CoV-2 genome replication and transcription; it is proteolytically cleaved into 16 non-structural proteins (nsps), several of which (e.g. nsp5 / Mpro, nsp12 / RdRp) are primary antiviral drug targets |
| Bioactivity type | IC50 (half-maximal inhibitory concentration, nM) |
| ChEMBL query | target.search('coronavirus') → target_chembl_id[6] |
Query ChEMBL for SARS-CoV-2 Replicase Polyprotein IC50 records, handle missing values, and classify compounds into active / inactive / intermediate classes.
Compute Lipinski descriptors via RDKit, convert IC50 to pIC50, and visualise the chemical space distribution of active vs inactive compounds.
Export SMILES to molecule.smi and compute 881-bit PubChem fingerprints using PaDEL-Descriptor via padel.sh.
Apply VarianceThreshold feature selection, split data 80/20, train a Random Forest Regressor, and evaluate on the held-out test set.
Benchmark 40+ scikit-learn regression algorithms automatically using LazyPredict on the same 80/20 split.
Train the final Random Forest (n_estimators=500) on the full dataset, export COVID19_model.pkl, and deploy via the Streamlit web application.
ChEMBL → IC50 data → Activity classification
→ Lipinski EDA → pIC50 conversion
→ PubChem fingerprints (PaDEL)
→ VarianceThreshold feature selection
→ Random Forest QSAR model
→ LazyPredict benchmarking
→ COVID19_model.pkl
→ Streamlit web app (interactive pIC50 prediction)
bioactivity-prediction-of-COIVD-19/
│
├── 1-Data-Collection-COVID19.ipynb # ChEMBL query and activity labelling
├── 2-Exploratory-Data-Analysis-COVID19.ipynb # Lipinski EDA, pIC50, visualisations
├── 3-Descriptor-Calculation-COVID19.ipynb # PaDEL PubChem fingerprints
├── 4-Model_Building_COVID19.ipynb # Random Forest training and evaluation
├── 5-Model-Comparison-COVID19.ipynb # LazyPredict multi-algorithm benchmark
├── 6-Model-deployment-COVID19.ipynb # Final model and pickle export
│
├── padel.sh # Shell script to run PaDEL-Descriptor
├── PaDEL-Descriptor/ # PaDEL-Descriptor JAR and XML config
│
├── bioactivity-prediction-app-main/ # Streamlit web application
│ ├── app.py # Main Streamlit application
│ ├── COVID19_model.pkl # Deployed trained model
│ ├── descriptor_list.csv # Selected feature names for prediction
│ ├── descriptors_output.csv # PaDEL output (generated at runtime)
│ ├── PaDEL-Descriptor/ # PaDEL JAR for app-side calculation
│ ├── logo.png # App logo
│ ├── compounds.txt # Example input file
│ ├── requirements.txt # App dependencies
│ └── bioactivity_prediction_app.ipynb # App development notebook
│
├── 1_bioactivity_data_Data_Collection_part.csv # Raw ChEMBL IC50 records
├── 2_bioactivity_data_PROCESSED_Data_Collection_part.csv # Cleaned + activity class labels
├── 3_COVID19_bioactivity_data_3class_pIC50_*.csv # + Lipinski descriptors + pIC50
├── 4_COVID19_bioactivity_data_3class_pIC50_pubchem_fp_*.cvs # PubChem fingerprints + pIC50
│
├── molecule.smi # SMILES input for PaDEL
├── descriptors_output.csv # Full 881-bit fingerprint matrix
├── descriptor_list.csv # Variance-filtered features (deployment)
├── COVID19_model.pkl # Serialised trained model
│
├── EDA_plot_bioactivity_class.pdf # Bioactivity class frequency plot
├── EDA_plot_MS_vs_LogP.pdf # MW vs LogP scatter plot
├── EDA_BP_plot_pIC50.pdf # pIC50 box plot (active vs inactive)
└── results.zip # Compressed results archive
| Parameter | Value |
|---|---|
| Target | SARS-CoV-2 Replicase Polyprotein |
| ChEMBL query | target.search('coronavirus') → index 6 |
| Activity type | IC50 (nM) |
| Data source | ChEMBL database |
| Preprocessing | Rows with missing standard_value removed; NaN molecule_chembl_id dropped |
| Columns retained | molecule_chembl_id, canonical_smiles, standard_value, bioactivity_class |
| Class | IC50 threshold | Interpretation |
|---|---|---|
| Active | ≤ 1,000 nM | Potent inhibitors |
| Intermediate | 1,000 – 10,000 nM | Moderate activity; excluded from binary model training |
| Inactive | ≥ 10,000 nM | Non-inhibitors |
IC50 values are capped at 100,000,000 nM (100 μM) before conversion to prevent extreme pIC50 values.
IC50 → pIC50 conversion:
pIC50 = −log₁₀(IC50 in M)
| Descriptor | Definition |
|---|---|
MW |
Molecular weight (Da) |
LogP |
Octanol–water partition coefficient |
NumHDonors |
Number of hydrogen bond donors |
NumHAcceptors |
Number of hydrogen bond acceptors |
- Type: PubChem fingerprints (
PubchemFingerprinter.xml) - Dimensionality: 881 binary bits per compound
- Preprocessing: Salt removal, nitro group standardisation
- Tool: PaDEL-Descriptor (Java ≥ JRE 1.8)
# padel.sh — executed by Notebook 3 and the Streamlit app
java -Xms1G -Xmx1G -Djava.awt.headless=true \
-jar ./PaDEL-Descriptor/PaDEL-Descriptor.jar \
-removesalt -standardizenitro -fingerprints \
-descriptortypes ./PaDEL-Descriptor/PubchemFingerprinter.xml \
-dir ./ -file descriptors_output.csvsklearn.feature_selection.VarianceThreshold is applied to remove near-constant features:
| Context | Threshold | Notes |
|---|---|---|
| Notebooks 4 & 5 (exploration) | 0.16 (≈ 80/20 split) | Model building and LazyPredict comparison |
| Notebook 6 (deployment) | 0.10 | Final model; selected columns saved to descriptor_list.csv |
Random Forest Regressor (sklearn.ensemble.RandomForestRegressor)
| Parameter | Notebook 4 (exploration) | Notebook 6 (deployment) |
|---|---|---|
n_estimators |
100 | 500 |
random_state |
100 | 42 |
| Training set | 80% | Full dataset |
| Test set | 20% | Full dataset (training evaluation) |
| Evaluation | R² | R², MSE |
LazyRegressor automatically fits and evaluates all available scikit-learn regression algorithms on the same 80/20 split, reporting R², RMSE, and computation time for each. Results are visualised as horizontal bar charts.
import pickle
model = pickle.load(open('COVID19_model.pkl', 'rb'))
predictions = model.predict(X_new) # X_new must match descriptor_list.csv columnsThe bioactivity-prediction-app-main/ directory contains a fully deployable Streamlit application for interactive compound prediction.
User uploads .txt file (SMILES + compound names)
│
▼
PaDEL-Descriptor calculates PubChem fingerprints on-the-fly
│
▼
Descriptor subset aligned to descriptor_list.csv
│
▼
COVID19_model.pkl predicts pIC50 for each compound
│
▼
Prediction table displayed in browser
│
▼
CSV download link generated
The app accepts a space-delimited .txt file with two columns — SMILES and compound name:
CC(=O)Oc1ccccc1C(=O)O Aspirin
c1ccc2ccccc2c1 Naphthalene
cd bioactivity-prediction-app-main
# Install dependencies
pip install -r requirements.txt
# Launch the app
streamlit run app.pyThe app will open at http://localhost:8501 in your browser.
streamlit==0.71.0
pandas==1.1.3
Pillow
pickle
subprocess
Note: Java (JRE ≥ 1.8) must be installed and accessible for PaDEL descriptor calculation within the app.
| File | Description |
|---|---|
1_bioactivity_data_Data_Collection_part.csv |
Raw ChEMBL IC50 records |
2_bioactivity_data_PROCESSED_Data_Collection_part.csv |
Cleaned data with activity class labels |
3_COVID19_bioactivity_data_3class_pIC50_*.csv |
+ Lipinski descriptors + pIC50 (3 classes) |
4_COVID19_bioactivity_data_3class_pIC50_pubchem_fp_*.cvs |
PubChem fingerprints (881-bit) + pIC50 |
descriptors_output.csv |
Full PaDEL fingerprint matrix |
descriptor_list.csv |
Variance-filtered feature names for deployment |
molecule.smi |
SMILES file used as PaDEL input |
COVID19_model.pkl |
Serialised Random Forest model (pickle) |
EDA_plot_bioactivity_class.pdf |
Bioactivity class frequency bar chart |
EDA_plot_MS_vs_LogP.pdf |
MW vs LogP scatter plot coloured by class |
EDA_BP_plot_pIC50.pdf |
pIC50 box plot: active vs inactive |
results.zip |
Compressed archive of all CSV and PDF outputs |
pip install chembl_webresource_client rdkit pandas numpy scikit-learn \
seaborn matplotlib lazypredict streamlit Pillow| Package | Purpose |
|---|---|
chembl_webresource_client |
ChEMBL database query |
rdkit |
Lipinski descriptors, SMILES processing |
pandas / numpy |
Data manipulation |
scikit-learn |
Random Forest, VarianceThreshold, metrics |
seaborn / matplotlib |
Visualisation |
lazypredict |
Multi-algorithm benchmarking (Notebook 5) |
streamlit |
Web application deployment |
Pillow |
Logo image handling in the app |
Requires Java Runtime Environment (JRE) ≥ 1.8.
# Ubuntu / Debian
sudo apt install -y default-jre
# macOS (Homebrew)
brew install --cask temurin
# Verify
java -versionThe PaDEL-Descriptor/ directory containing the JAR file and fingerprint XML must be present in the working directory when running padel.sh or the Streamlit app.
Execute notebooks sequentially:
jupyter notebook| Step | Notebook | Action |
|---|---|---|
| 1 | 1-Data-Collection-COVID19.ipynb |
Query ChEMBL, retrieve IC50, classify compounds |
| 2 | 2-Exploratory-Data-Analysis-COVID19.ipynb |
Lipinski EDA, pIC50 conversion, visualisations |
| 3 | 3-Descriptor-Calculation-COVID19.ipynb |
Run PaDEL fingerprints via padel.sh |
| 4 | 4-Model_Building_COVID19.ipynb |
Train and evaluate Random Forest (80/20 split) |
| 5 | 5-Model-Comparison-COVID19.ipynb |
Benchmark all sklearn regressors with LazyPredict |
| 6 | 6-Model-deployment-COVID19.ipynb |
Train final model, export COVID19_model.pkl |
- Prepare a
.txtfile with your query SMILES (see input format above). - Launch the app:
cd bioactivity-prediction-app-main streamlit run app.py - Upload your
.txtfile in the sidebar and click Predict. - Download the predictions as CSV.
import pickle
import pandas as pd
# Load model and feature list
model = pickle.load(open('COVID19_model.pkl', 'rb'))
desc_list = pd.read_csv('descriptor_list.csv')
# Load pre-computed PaDEL fingerprints for query compounds
query_fp = pd.read_csv('descriptors_output.csv').iloc[:, 1:] # drop Name column
query_fp = query_fp[desc_list.columns] # align to training features
# Predict pIC50
predictions = model.predict(query_fp)
print(predictions)Rashid Hussain, PhD, RSci, MRSC
Postdoctoral Researcher in Computational Pathology
Humanitas Research Hospital (IRCCS), Milan, Italy
rashid.bioinfo@gmail.com · https://rashid-bioinfo.github.io
QSAR · Cheminformatics · Machine Learning for Antiviral Drug Discovery




