ERα Virtual Screening of Ayurvedic Phytochemicals
By Panigrahi Ind. · Published July 27, 2026
Computational drug discovery pipeline screening ~500 Ayurvedic phytochemicals against estrogen receptor alpha using molecular docking and deep learning scoring.
- drug-discovery
- molecular-docking
- phytochemistry
- structure-based-design
- ayurveda
- computational-biology
Inside this notebook
# Virtual Screening of Ayurvedic Phytochemicals against Estrogen Receptor Alpha (ERα) ## Target **Estrogen Receptor Alpha (ERα)** — a nuclear receptor and transcription factor (UniProt: P03372) implicated in breast cancer, osteoporosis, and cardiovascular disease. The ligand-binding domain (LBD) is a validated drug target for selective estrogen receptor modulators (SERMs) and phytoestrogens. ## Workflow 1. **Receptor Acquisition** — Query RCSB PDB for the highest-resolution wild-type human ERα LBD crystal structure 2. **Receptor Preparation** — Remove waters/ligands, add hydrogens, assign charges → PDBQT 3. **Compound Library** — Assemble ~500 phytochemicals from IMPPAT 2.0, PubChem, and ChEMBL (Ayurvedic medicinal plants) 4. **Ligand Preparation** — 3D conformer generation (ETKDGv3 + MMFF94) → PDBQT via Meeko 5. **Pocket Detection** — Co-crystallized ligand centroid + ProDy validation → grid box 6. **Molecular Docking** — **GNINA** (CNN-scoring, primary) **+ AutoDock Vina** (comparison), exhaustiveness=8, 9 modes, 8 CPUs 7. **Docking Comparison** — Spearman rank correlation, score distributions, consensus hits (top-20 overlap) 8. **Interaction Diagrams** — 2D interaction maps for top 20 consensus compounds 9. **ADMET Profiling** — Lipinski Ro5, Veber, QED, PAINS, GI absorption, BBB permeation 10. **Report** — CSV exports, plots, and self-contained HTML report ## Data Sources | Source | Role | |--------|------| | RCSB PDB | ERα crystal structure | | IMPPAT 2.0 | Primary ph…
# ============================================================
# Cell 1a: Install System Libraries & Python Packages
# ============================================================
import subprocess, sys
print("=== Installing system libraries ===")
try:
subprocess.run(["apt-get", "update", "-qq"],
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, timeout=60)
subprocess.run(["apt-get", "install", "-y", "-qq",
"libxrender1", "libxext6", "libx11-6"],
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, timeout=60)
print(" ✓ System libraries (libXrender, libXext, libX11)")
except Exception as e:
print(f" ⚠ System libs: {e}")
print("\n=== Installing Python packages ===")
for pkg in ["rdkit", "gemmi", "meeko", "vina", "biopandas",
…=== Installing system libraries === ✓ System libraries (libXrender, libXext, libX11) === Installing Python packages === rdkit... ✓ gemmi... ✓ meeko... ✓ vina... ✓ biopandas... ✓ prody... ✓ openbabel-wheel... ✓ pillow... ✓ ✓ All Python packages installed.
# ============================================================
# Cell 1b: Download GNINA Binary (CPU, v1.1) & Verify
# ============================================================
import os, stat, subprocess, urllib.request
GNINA_BIN = "/usr/local/bin/gnina"
GNINA_URL = "https://github.com/gnina/gnina/releases/download/v1.1/gnina"
if not os.path.exists(GNINA_BIN):
print(f"Downloading GNINA v1.1 (CPU, ~292 MB) ...")
print(f" URL: {GNINA_URL}")
urllib.request.urlretrieve(GNINA_URL, GNINA_BIN)
os.chmod(GNINA_BIN, os.stat(GNINA_BIN).st_mode | stat.S_IEXEC | stat.S_IXGRP | stat.S_IXOTH)
size_mb = os.path.getsize(GNINA_BIN) / 1024 / 1024
print(f" ✓ Saved to {GNINA_BIN} ({size_mb:.0f} MB)")
else:
size_mb = os.path.getsize(GNINA_BIN) / 1024 / 1024
print(f" ✓ GNINA already present ({size_mb:.0f} MB)")
…Downloading GNINA v1.1 (CPU, ~292 MB) ... URL: https://github.com/gnina/gnina/releases/download/v1.1/gnina ✓ Saved to /usr/local/bin/gnina (292 MB) ✓ GNINA verified: Input:
# ============================================================
# Cell 1c: Import Libraries & Create Directory Structure
# ============================================================
import numpy as np
import pandas as pd
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import seaborn as sns
from rdkit import Chem, rdBase
from rdkit.Chem import (
AllChem, Descriptors, Draw, QED, FilterCatalog,
rdMolDescriptors, Lipinski, rdDistGeom, rdForceFieldHelpers
)
from rdkit.Chem import PandasTools
from rdkit.Chem.Draw import rdMolDraw2D
…RDKit: 2026.03.4 Pandas: 2.2.3 NumPy: 2.1.2 ProDy: 2.6.1 Vina: Python API ✓ GNINA: /usr/local/bin/gnina ✓ Output dir: /home/user/vs_results Directories: ['receptor', 'ligands_sdf', 'ligands_pdbqt', 'docking_vina', 'docking_gnina', 'interactions', 'plots', 'reports'] ✓ All imports verified. Environment ready.
# ============================================================
# Cell 2: Download Highest-Quality Human ERα Structure from PDB
# ============================================================
import requests, json
print("=== Querying RCSB PDB for human ERα LBD structures ===\n")
# RCSB Search API v2 query
query = {
"query": {
"type": "group",
"logical_operator": "and",
"nodes": [
{
"type": "terminal",
"service": "text",
"parameters": {
"attribute": "rcsb_polymer_entity_container_identifiers.reference_sequence_identifiers.database_accession",
…=== Querying RCSB PDB for human ERα LBD structures === Found 469 ERα X-ray structures (resolution ≤ 3.0 Å, ligand-bound) Showing top 20 by resolution: 7BAA | 1.10 Å | unknown | mut: WT 8BZC | 1.10 Å | unknown | mut: WT 8BZW | 1.10 Å | unknown | mut: WT 8C04 | 1.10 Å | unknown | mut: WT 7B9R | 1.15 Å | unknown | mut: WT 7B9T | 1.15 Å | unknown | mut: WT 6HMU | 1.20 Å | unknown | mut: C38N, S45C 7BA8 | 1.20 Å | unknown | mut: WT 8APS | 1.20 Å | unknown | mut: WT 8BX3 | 1.20 Å…
# ============================================================
# Cell 3: Build Ayurvedic Phytochemical Dataset (~500 compounds)
# ============================================================
import requests, time, random
from rdkit import Chem
from rdkit.Chem import Descriptors
print("=== Building Ayurvedic Phytochemical Library ===\n")
print("Strategy: Query PubChem by compound name → guaranteed valid SMILES\n")
# ── Curated list of Ayurvedic phytochemical names ──────────
COMPOUND_NAMES = {
"Curcuma longa": [
"curcumin", "demethoxycurcumin", "bisdemethoxycurcumin",
"ar-turmerone", "turmerone", "cyclocurcumin", "curcumenol",
"curdione", "germacrone", "zederone",
],
"Withania somnifera": [
…=== Building Ayurvedic Phytochemical Library === Strategy: Query PubChem by compound name → guaranteed valid SMILES Total compound names: 270 from 33 groups Querying PubChem PUG REST... [50/270] found=50, failed=0 [100/270] found=98, failed=2 [150/270] found=146, failed=4 [200/270] found=192, failed=8 [250/270] found=242, failed=8 [270/270] found=262, failed=8 PubChem: 262 found, 8 not found === Deduplicating and filtering === After dedup + MW filter: 250 unique compounds =…
# ============================================================
# Cell 3b: Expand Library to ~500 Compounds (Supplementary Query)
# ============================================================
import requests, time, random
from rdkit import Chem
from rdkit.Chem import Descriptors
print("=== Expanding library with additional compounds ===\n")
# Additional compound names to reach ~500
ADDITIONAL_NAMES = {
"Curcuma longa (extra)": [
"bisacurone", "curcumol", "procurcumenol", "isoprocurcumenol",
"curcumenone", "curcumanolide A", "curcumanolide B",
"curcumanolide C", "curcumanolide D", "curcumanolide E",
],
"Withania somnifera (extra)": [
"withanolide F", "withanolide G", "withanolide H",
…This is a preview. Open the live notebook to see all 13 cells with their charts and full outputs, or fork it into your own Clusy workspace.