Spaces:
Running
Running
Commit ·
d96163c
1
Parent(s): 1d12809
Rebuild Space as static no-GAT explorer (Ablation 2)
Browse filesReplace the broken Gradio app (Jinja2 unhashable-dict crash) with a static
front-end for the current 'No Drug Graphs' model. Data is served cross-origin
from the project's GitHub Pages so the Space and Pages share one source of truth.
- .gitattributes +2 -35
- .gitignore +0 -68
- APP_GUIDE.md +0 -277
- DEPLOYMENT.md +0 -221
- FILES.md +0 -214
- README.md +16 -402
- SETUP.md +0 -351
- SPACE_README.md +0 -157
- USER_SETUP_SUMMARY.md +0 -302
- app.js +233 -0
- app.py +0 -609
- cleanup.sh +0 -59
- code.ipynb +0 -0
- drug_effects.csv +0 -0
- drug_nodes.csv +0 -0
- drugs_interactions.csv +0 -0
- graph_embeddings.npy +0 -3
- index.html +89 -0
- node_to_idx.npy +0 -3
- protein_nodes_with_embeddings.csv +0 -0
- pyproject.toml +0 -7
- requirements.txt +0 -11
- requirements_app.txt +0 -14
- start_app.sh +0 -24
- style.css +98 -0
- test_app.py +0 -157
- top_50_predicted_drug_effects.csv +0 -51
- top_50_predicted_drug_protein.csv +0 -51
.gitattributes
CHANGED
|
@@ -1,35 +1,2 @@
|
|
| 1 |
-
*.
|
| 2 |
-
*
|
| 3 |
-
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 4 |
-
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
| 5 |
-
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
| 6 |
-
*.ftz filter=lfs diff=lfs merge=lfs -text
|
| 7 |
-
*.gz filter=lfs diff=lfs merge=lfs -text
|
| 8 |
-
*.h5 filter=lfs diff=lfs merge=lfs -text
|
| 9 |
-
*.joblib filter=lfs diff=lfs merge=lfs -text
|
| 10 |
-
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
| 11 |
-
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
| 12 |
-
*.model filter=lfs diff=lfs merge=lfs -text
|
| 13 |
-
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
| 14 |
-
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 15 |
-
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 16 |
-
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 17 |
-
*.ot filter=lfs diff=lfs merge=lfs -text
|
| 18 |
-
*.parquet filter=lfs diff=lfs merge=lfs -text
|
| 19 |
-
*.pb filter=lfs diff=lfs merge=lfs -text
|
| 20 |
-
*.pickle filter=lfs diff=lfs merge=lfs -text
|
| 21 |
-
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 22 |
-
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 23 |
-
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 24 |
-
*.rar filter=lfs diff=lfs merge=lfs -text
|
| 25 |
-
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
| 26 |
-
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
| 27 |
-
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
| 28 |
-
*.tar filter=lfs diff=lfs merge=lfs -text
|
| 29 |
-
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 30 |
-
*.tgz filter=lfs diff=lfs merge=lfs -text
|
| 31 |
-
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 32 |
-
*.xz filter=lfs diff=lfs merge=lfs -text
|
| 33 |
-
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
-
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
-
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
| 1 |
+
*.html linguist-language=HTML
|
| 2 |
+
* text=auto eol=lf
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.gitignore
DELETED
|
@@ -1,68 +0,0 @@
|
|
| 1 |
-
# Ignore everything by default
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
# But not these files:
|
| 5 |
-
!.gitignore
|
| 6 |
-
|
| 7 |
-
# Allow CSV files
|
| 8 |
-
!*.csv
|
| 9 |
-
|
| 10 |
-
# Allow Jupyter notebooks
|
| 11 |
-
!*.ipynb
|
| 12 |
-
|
| 13 |
-
# Allow Python files
|
| 14 |
-
!*.py
|
| 15 |
-
|
| 16 |
-
# Allow directories (so we can traverse into them)
|
| 17 |
-
!*/
|
| 18 |
-
|
| 19 |
-
# Ignore common large files even if they match above patterns
|
| 20 |
-
*.pkl
|
| 21 |
-
*.npy
|
| 22 |
-
*.db
|
| 23 |
-
*.xml
|
| 24 |
-
*.h5
|
| 25 |
-
*.hdf5
|
| 26 |
-
|
| 27 |
-
# Ignore model checkpoints and weights
|
| 28 |
-
*.pth
|
| 29 |
-
*.pt
|
| 30 |
-
*.ckpt
|
| 31 |
-
*.safetensors
|
| 32 |
-
|
| 33 |
-
# Ignore image outputs
|
| 34 |
-
*.png
|
| 35 |
-
*.jpg
|
| 36 |
-
*.jpeg
|
| 37 |
-
*.gif
|
| 38 |
-
*.svg
|
| 39 |
-
|
| 40 |
-
# Ignore compressed files
|
| 41 |
-
*.zip
|
| 42 |
-
*.tar
|
| 43 |
-
*.gz
|
| 44 |
-
*.rar
|
| 45 |
-
|
| 46 |
-
# Ignore Python cache
|
| 47 |
-
__pycache__/
|
| 48 |
-
*.pyc
|
| 49 |
-
*.pyo
|
| 50 |
-
*.pyd
|
| 51 |
-
.Python
|
| 52 |
-
|
| 53 |
-
# Ignore Jupyter checkpoints
|
| 54 |
-
.ipynb_checkpoints/
|
| 55 |
-
|
| 56 |
-
# Ignore environment files
|
| 57 |
-
.env
|
| 58 |
-
.venv
|
| 59 |
-
env/
|
| 60 |
-
venv/
|
| 61 |
-
ENV/
|
| 62 |
-
|
| 63 |
-
# Ignore IDE files
|
| 64 |
-
.vscode/
|
| 65 |
-
.idea/
|
| 66 |
-
*.swp
|
| 67 |
-
*.swo
|
| 68 |
-
*~
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
APP_GUIDE.md
DELETED
|
@@ -1,277 +0,0 @@
|
|
| 1 |
-
# 🚀 Gradio App Quick Start Guide
|
| 2 |
-
|
| 3 |
-
## What I Created
|
| 4 |
-
|
| 5 |
-
I've built a **fully interactive Gradio web app** for your Pharmacology Knowledge Graph that includes:
|
| 6 |
-
|
| 7 |
-
✅ **Drug search functionality** - Search by name or ChEMBL ID
|
| 8 |
-
✅ **Known interactions display** - View verified drug-target and drug-effect relationships
|
| 9 |
-
✅ **AI predictions** - See novel targets and therapeutic uses predicted by your model
|
| 10 |
-
✅ **Interactive network visualization** - Beautiful Plotly graph showing drug mechanisms
|
| 11 |
-
✅ **Ready for Hugging Face deployment** - One-click hosting on HF Spaces
|
| 12 |
-
|
| 13 |
-
---
|
| 14 |
-
|
| 15 |
-
## 📁 Files Created
|
| 16 |
-
|
| 17 |
-
| File | Purpose |
|
| 18 |
-
|------|---------|
|
| 19 |
-
| `app.py` | Main Gradio application (500+ lines) |
|
| 20 |
-
| `requirements_app.txt` | Python dependencies for the app |
|
| 21 |
-
| `run_app.sh` | Local testing script |
|
| 22 |
-
| `DEPLOYMENT.md` | Step-by-step HF Spaces deployment guide |
|
| 23 |
-
| `SPACE_README.md` | README for your Hugging Face Space |
|
| 24 |
-
|
| 25 |
-
---
|
| 26 |
-
|
| 27 |
-
## 🎮 How to Use It
|
| 28 |
-
|
| 29 |
-
### Option 1: Test Locally (Recommended First)
|
| 30 |
-
|
| 31 |
-
```bash
|
| 32 |
-
# Run the app on your machine
|
| 33 |
-
./run_app.sh
|
| 34 |
-
|
| 35 |
-
# Or manually:
|
| 36 |
-
python app.py
|
| 37 |
-
```
|
| 38 |
-
|
| 39 |
-
Then open: **http://localhost:7860**
|
| 40 |
-
|
| 41 |
-
### Option 2: Deploy to Hugging Face Spaces
|
| 42 |
-
|
| 43 |
-
Follow the guide in `DEPLOYMENT.md`. Summary:
|
| 44 |
-
|
| 45 |
-
1. **Create Space** on huggingface.co/spaces
|
| 46 |
-
2. **Upload files:**
|
| 47 |
-
- `app.py`
|
| 48 |
-
- `requirements_app.txt` → rename to `requirements.txt`
|
| 49 |
-
- All CSV files (drug_nodes, protein_nodes, etc.)
|
| 50 |
-
- All NPY files (graph_embeddings, node_to_idx)
|
| 51 |
-
3. **Wait 2-3 minutes** for build
|
| 52 |
-
4. **Share your link!** `https://huggingface.co/spaces/YOUR_USERNAME/pharmacology-knowledge-graph`
|
| 53 |
-
|
| 54 |
-
---
|
| 55 |
-
|
| 56 |
-
## 🎨 App Features
|
| 57 |
-
|
| 58 |
-
### 1. Drug Search
|
| 59 |
-
- Type any drug name (e.g., "Morphine", "Aspirin")
|
| 60 |
-
- Or use ChEMBL ID (e.g., "CHEMBL70")
|
| 61 |
-
- Get auto-suggestions as you type
|
| 62 |
-
|
| 63 |
-
### 2. Information Panels
|
| 64 |
-
|
| 65 |
-
**Left Side:**
|
| 66 |
-
- Drug basic info (name, ChEMBL ID, SMILES)
|
| 67 |
-
- Known protein targets with binding affinity (pChEMBL)
|
| 68 |
-
- Known clinical effects (indications)
|
| 69 |
-
|
| 70 |
-
**Right Side:**
|
| 71 |
-
- **Predicted novel targets** (drug repurposing opportunities)
|
| 72 |
-
- **Predicted novel effects** (new therapeutic uses)
|
| 73 |
-
- Confidence scores and similarity metrics
|
| 74 |
-
|
| 75 |
-
### 3. Interactive Network Graph
|
| 76 |
-
|
| 77 |
-
Shows your drug as the **center node** with:
|
| 78 |
-
- 🔵 **Blue nodes** = Known protein targets (solid edges)
|
| 79 |
-
- 🟢 **Green nodes** = Predicted targets (dashed edges)
|
| 80 |
-
- 🟡 **Yellow nodes** = Known effects (solid edges)
|
| 81 |
-
- 🟨 **Light yellow nodes** = Predicted effects (dashed edges)
|
| 82 |
-
|
| 83 |
-
**Controls:**
|
| 84 |
-
- Toggle known/predicted interactions on/off
|
| 85 |
-
- Adjust number of nodes displayed (10-50)
|
| 86 |
-
- Hover over nodes for details
|
| 87 |
-
- Zoom/pan the graph
|
| 88 |
-
|
| 89 |
-
---
|
| 90 |
-
|
| 91 |
-
## 📊 Example Queries to Try
|
| 92 |
-
|
| 93 |
-
| Drug | What You'll See |
|
| 94 |
-
|------|----------------|
|
| 95 |
-
| **Morphine** | Opioid receptors (μ, δ, κ), analgesic effects, similar drugs like Fentanyl |
|
| 96 |
-
| **Aspirin** | COX-1/COX-2 inhibition, anti-inflammatory effects, cardiovascular uses |
|
| 97 |
-
| **Talazoparib** | PARP1/2 targets + **predicted** PARP3/4 homologs (novel finding!) |
|
| 98 |
-
| **Metformin** | AMPK activation, diabetes treatment, **predicted** anti-aging effects |
|
| 99 |
-
| **Rivaroxaban** | Known anticoagulation + **predicted** myocardial infarction prevention |
|
| 100 |
-
|
| 101 |
-
---
|
| 102 |
-
|
| 103 |
-
## 🏗️ Technical Architecture
|
| 104 |
-
|
| 105 |
-
```
|
| 106 |
-
User Input (Drug Name)
|
| 107 |
-
↓
|
| 108 |
-
[Search Function] → Find drug in database
|
| 109 |
-
↓
|
| 110 |
-
[Embedding Lookup] → Get drug's 128-dim vector
|
| 111 |
-
↓
|
| 112 |
-
[Similarity Computation] → Cosine similarity to all proteins/effects
|
| 113 |
-
↓
|
| 114 |
-
[Ranking & Filtering] → Top-K predictions, remove known interactions
|
| 115 |
-
↓
|
| 116 |
-
[Network Builder] → Create interactive Plotly graph
|
| 117 |
-
↓
|
| 118 |
-
Display Results
|
| 119 |
-
```
|
| 120 |
-
|
| 121 |
-
**Key Components:**
|
| 122 |
-
|
| 123 |
-
1. **Data Loading** (startup):
|
| 124 |
-
- CSV files → Pandas DataFrames
|
| 125 |
-
- NPY files → NumPy arrays (embeddings)
|
| 126 |
-
- Cached in memory for fast access
|
| 127 |
-
|
| 128 |
-
2. **Search Engine**:
|
| 129 |
-
- Fuzzy matching on drug names
|
| 130 |
-
- ChEMBL ID exact matching
|
| 131 |
-
- Returns top 20 matches
|
| 132 |
-
|
| 133 |
-
3. **Prediction Engine**:
|
| 134 |
-
- Cosine similarity: `cos(drug_emb, target_emb)`
|
| 135 |
-
- Threshold filtering: High (>0.5), Medium (>0.45), Low
|
| 136 |
-
- Excludes known interactions
|
| 137 |
-
|
| 138 |
-
4. **Visualization**:
|
| 139 |
-
- NetworkX for graph layout (spring layout)
|
| 140 |
-
- Plotly for interactive rendering
|
| 141 |
-
- Color-coded by node type and known/predicted status
|
| 142 |
-
|
| 143 |
-
---
|
| 144 |
-
|
| 145 |
-
## 🎯 Deployment Checklist
|
| 146 |
-
|
| 147 |
-
### Pre-Deployment (Do This First)
|
| 148 |
-
|
| 149 |
-
- [ ] Test app locally: `./run_app.sh`
|
| 150 |
-
- [ ] Try 5-10 different drugs
|
| 151 |
-
- [ ] Check network visualization works
|
| 152 |
-
- [ ] Verify predictions make sense
|
| 153 |
-
|
| 154 |
-
### Hugging Face Setup
|
| 155 |
-
|
| 156 |
-
- [ ] Create HF account (if needed)
|
| 157 |
-
- [ ] Create new Space
|
| 158 |
-
- [ ] Choose "Gradio" SDK
|
| 159 |
-
- [ ] Select CPU basic (free tier)
|
| 160 |
-
|
| 161 |
-
### File Upload
|
| 162 |
-
|
| 163 |
-
- [ ] Upload `app.py`
|
| 164 |
-
- [ ] Rename `requirements_app.txt` → `requirements.txt` and upload
|
| 165 |
-
- [ ] Upload all CSV files:
|
| 166 |
-
- [ ] `drug_nodes.csv`
|
| 167 |
-
- [ ] `protein_nodes_with_embeddings.csv`
|
| 168 |
-
- [ ] `drug_effects.csv`
|
| 169 |
-
- [ ] `drugs_interactions.csv`
|
| 170 |
-
- [ ] Upload NPY files:
|
| 171 |
-
- [ ] `graph_embeddings.npy`
|
| 172 |
-
- [ ] `node_to_idx.npy`
|
| 173 |
-
- [ ] Use `SPACE_README.md` content for Space README
|
| 174 |
-
|
| 175 |
-
### Post-Deployment
|
| 176 |
-
|
| 177 |
-
- [ ] Wait for build (check logs)
|
| 178 |
-
- [ ] Test live app
|
| 179 |
-
- [ ] Share link on social media
|
| 180 |
-
- [ ] Add to competition submission
|
| 181 |
-
|
| 182 |
-
---
|
| 183 |
-
|
| 184 |
-
## 💡 Pro Tips
|
| 185 |
-
|
| 186 |
-
### For Competitions/Demos
|
| 187 |
-
|
| 188 |
-
1. **Prepare example queries** - Have 3-5 drugs ready to show during demo
|
| 189 |
-
2. **Highlight novel predictions** - Point out predicted interactions not in training data
|
| 190 |
-
3. **Show validation** - Mention the ~90% precision rate
|
| 191 |
-
4. **Explain the network** - Walk through how to interpret the visualization
|
| 192 |
-
|
| 193 |
-
### For Presentations
|
| 194 |
-
|
| 195 |
-
**30-second pitch:**
|
| 196 |
-
> "This app lets you explore how drugs work using AI. Type any drug name, and you'll see known targets plus AI-predicted new uses. The network shows everything visually. We trained it on 800 drugs and validated 90% accuracy on predictions."
|
| 197 |
-
|
| 198 |
-
**Key talking points:**
|
| 199 |
-
- Novel approach: Learns from drug structure + protein sequence
|
| 200 |
-
- Real data: 800 FDA drugs, 200 proteins, 400 effects
|
| 201 |
-
- Practical use: Drug repurposing, target discovery, safety prediction
|
| 202 |
-
- Validated: 90% of top predictions are biologically coherent
|
| 203 |
-
|
| 204 |
-
### For Further Development
|
| 205 |
-
|
| 206 |
-
Want to enhance it? Easy additions:
|
| 207 |
-
|
| 208 |
-
```python
|
| 209 |
-
# 1. Add SMILES input for novel molecules
|
| 210 |
-
def predict_from_smiles(smiles_string):
|
| 211 |
-
# Use your Ridge regression model
|
| 212 |
-
# Return predictions
|
| 213 |
-
|
| 214 |
-
# 2. Export results to CSV
|
| 215 |
-
def export_predictions(drug_name):
|
| 216 |
-
# Generate downloadable file
|
| 217 |
-
return gr.File(...)
|
| 218 |
-
|
| 219 |
-
# 3. Batch analysis
|
| 220 |
-
def analyze_multiple_drugs(drug_list):
|
| 221 |
-
# Loop and aggregate results
|
| 222 |
-
```
|
| 223 |
-
|
| 224 |
-
---
|
| 225 |
-
|
| 226 |
-
## 🐛 Troubleshooting
|
| 227 |
-
|
| 228 |
-
### "Module not found" error
|
| 229 |
-
```bash
|
| 230 |
-
# Install missing package
|
| 231 |
-
uv pip install <package_name>
|
| 232 |
-
```
|
| 233 |
-
|
| 234 |
-
### "File not found" error
|
| 235 |
-
```bash
|
| 236 |
-
# Check all CSV/NPY files are in same directory as app.py
|
| 237 |
-
ls *.csv *.npy
|
| 238 |
-
```
|
| 239 |
-
|
| 240 |
-
### Slow performance
|
| 241 |
-
- Predictions are cached after first run
|
| 242 |
-
- Consider pre-computing all predictions (add CSV files)
|
| 243 |
-
- Hugging Face Spaces: upgrade to CPU upgrade ($0.03/hr)
|
| 244 |
-
|
| 245 |
-
### Network visualization not showing
|
| 246 |
-
- Check Plotly is installed: `uv pip install plotly`
|
| 247 |
-
- Try reducing max_nodes in settings
|
| 248 |
-
|
| 249 |
-
---
|
| 250 |
-
|
| 251 |
-
## 📈 Next Steps
|
| 252 |
-
|
| 253 |
-
1. **Test locally** → Run `./run_app.sh` and try it out
|
| 254 |
-
2. **Deploy to HF** → Follow `DEPLOYMENT.md` guide
|
| 255 |
-
3. **Share** → Get the public URL and share widely
|
| 256 |
-
4. **Iterate** → Gather feedback, add features
|
| 257 |
-
|
| 258 |
-
---
|
| 259 |
-
|
| 260 |
-
## 🎉 You're Ready!
|
| 261 |
-
|
| 262 |
-
You now have a **professional, interactive web app** that:
|
| 263 |
-
- ✅ Showcases your research
|
| 264 |
-
- ✅ Is easy to use (no code required for users)
|
| 265 |
-
- ✅ Deploys with one click
|
| 266 |
-
- ✅ Looks impressive in competitions/demos
|
| 267 |
-
|
| 268 |
-
**Questions?** Check:
|
| 269 |
-
- `DEPLOYMENT.md` for HF Spaces setup
|
| 270 |
-
- `app.py` comments for code details
|
| 271 |
-
- GitHub issues for community support
|
| 272 |
-
|
| 273 |
-
---
|
| 274 |
-
|
| 275 |
-
**Good luck with your competition! 🚀**
|
| 276 |
-
|
| 277 |
-
*P.S. - Once deployed, share the link! People love interactive ML demos.*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DEPLOYMENT.md
DELETED
|
@@ -1,221 +0,0 @@
|
|
| 1 |
-
# Hugging Face Space Deployment Guide
|
| 2 |
-
|
| 3 |
-
## 🚀 Deploy to Hugging Face Spaces
|
| 4 |
-
|
| 5 |
-
### Step 1: Create a New Space
|
| 6 |
-
|
| 7 |
-
1. Go to [Hugging Face Spaces](https://huggingface.co/spaces)
|
| 8 |
-
2. Click "Create new Space"
|
| 9 |
-
3. Choose:
|
| 10 |
-
- **Space name:** `pharmacology-knowledge-graph`
|
| 11 |
-
- **License:** MIT
|
| 12 |
-
- **Space SDK:** Gradio
|
| 13 |
-
- **Space hardware:** CPU basic (free tier works fine)
|
| 14 |
-
|
| 15 |
-
### Step 2: Upload Required Files
|
| 16 |
-
|
| 17 |
-
Upload these files to your Space:
|
| 18 |
-
|
| 19 |
-
**Required files:**
|
| 20 |
-
```
|
| 21 |
-
app.py # Main Gradio app
|
| 22 |
-
requirements_app.txt # Python dependencies (rename to requirements.txt)
|
| 23 |
-
drug_nodes.csv # Drug metadata
|
| 24 |
-
protein_nodes_with_embeddings.csv # Protein data
|
| 25 |
-
drug_effects.csv # Clinical effects
|
| 26 |
-
drugs_interactions.csv # Known drug-protein interactions
|
| 27 |
-
graph_embeddings.npy # Trained embeddings
|
| 28 |
-
node_to_idx.npy # Node index mapping
|
| 29 |
-
top_50_predicted_drug_protein.csv # Pre-computed predictions (optional)
|
| 30 |
-
top_50_predicted_drug_effects.csv # Pre-computed predictions (optional)
|
| 31 |
-
```
|
| 32 |
-
|
| 33 |
-
**File structure on Hugging Face:**
|
| 34 |
-
```
|
| 35 |
-
your-space/
|
| 36 |
-
├── app.py
|
| 37 |
-
├── requirements.txt # (rename requirements_app.txt)
|
| 38 |
-
├── README.md # Space description
|
| 39 |
-
├── drug_nodes.csv
|
| 40 |
-
├── protein_nodes_with_embeddings.csv
|
| 41 |
-
├── drug_effects.csv
|
| 42 |
-
├── drugs_interactions.csv
|
| 43 |
-
├── graph_embeddings.npy
|
| 44 |
-
├── node_to_idx.npy
|
| 45 |
-
├── top_50_predicted_drug_protein.csv
|
| 46 |
-
└── top_50_predicted_drug_effects.csv
|
| 47 |
-
```
|
| 48 |
-
|
| 49 |
-
### Step 3: Create Space README.md
|
| 50 |
-
|
| 51 |
-
Create a `README.md` in your Space with this content:
|
| 52 |
-
|
| 53 |
-
```markdown
|
| 54 |
-
---
|
| 55 |
-
title: Pharmacology Knowledge Graph Explorer
|
| 56 |
-
emoji: 💊
|
| 57 |
-
colorFrom: blue
|
| 58 |
-
colorTo: green
|
| 59 |
-
sdk: gradio
|
| 60 |
-
sdk_version: 4.44.0
|
| 61 |
-
app_file: app.py
|
| 62 |
-
pinned: false
|
| 63 |
-
license: mit
|
| 64 |
-
---
|
| 65 |
-
|
| 66 |
-
# 💊 Pharmacology Knowledge Graph Explorer
|
| 67 |
-
|
| 68 |
-
Explore drug-target-effect relationships using AI-powered predictions from a TransE knowledge graph model.
|
| 69 |
-
|
| 70 |
-
## Features
|
| 71 |
-
|
| 72 |
-
- 🔍 Search 800+ FDA-approved drugs
|
| 73 |
-
- 🎯 View known and predicted protein targets
|
| 74 |
-
- 💉 Discover potential therapeutic uses (drug repurposing)
|
| 75 |
-
- 🕸️ Interactive network visualization
|
| 76 |
-
|
| 77 |
-
## How It Works
|
| 78 |
-
|
| 79 |
-
This app uses a **TransE knowledge graph embedding model** trained on:
|
| 80 |
-
- 800+ FDA-approved drugs (from ChEMBL)
|
| 81 |
-
- 200+ human protein targets (with ESM-2 embeddings)
|
| 82 |
-
- 400+ clinical effects and indications
|
| 83 |
-
|
| 84 |
-
**Prediction method:** Cosine similarity in learned embedding space
|
| 85 |
-
**Model performance:** ~90% precision on top-50 predictions
|
| 86 |
-
|
| 87 |
-
## Example Queries
|
| 88 |
-
|
| 89 |
-
Try searching for:
|
| 90 |
-
- **Morphine** - See opioid receptor targets and analgesic effects
|
| 91 |
-
- **Aspirin** - COX inhibition and cardiovascular effects
|
| 92 |
-
- **Metformin** - Diabetes and potential repurposing candidates
|
| 93 |
-
|
| 94 |
-
## Citation
|
| 95 |
-
|
| 96 |
-
```bibtex
|
| 97 |
-
@software{pharmacology_graph_2025,
|
| 98 |
-
author = {Joe VonDahab},
|
| 99 |
-
title = {Pharmacology Knowledge Graph: Drug-Target-Effect Prediction},
|
| 100 |
-
year = {2025},
|
| 101 |
-
url = {https://github.com/JoeVonDahab/pharmacology-graph}
|
| 102 |
-
}
|
| 103 |
-
```
|
| 104 |
-
|
| 105 |
-
## Disclaimer
|
| 106 |
-
|
| 107 |
-
This is a research tool for exploratory analysis only. Predictions should be validated experimentally. Not for clinical use.
|
| 108 |
-
```
|
| 109 |
-
|
| 110 |
-
### Step 4: File Preparation Commands
|
| 111 |
-
|
| 112 |
-
Run these commands in your project directory:
|
| 113 |
-
|
| 114 |
-
```bash
|
| 115 |
-
# 1. Copy app requirements (rename for HF)
|
| 116 |
-
cp requirements_app.txt requirements.txt
|
| 117 |
-
|
| 118 |
-
# 2. Verify all data files exist
|
| 119 |
-
ls -lh *.csv *.npy
|
| 120 |
-
|
| 121 |
-
# Expected files:
|
| 122 |
-
# - drug_nodes.csv (~200KB)
|
| 123 |
-
# - protein_nodes_with_embeddings.csv (~500KB)
|
| 124 |
-
# - drug_effects.csv (~300KB)
|
| 125 |
-
# - drugs_interactions.csv (~2MB)
|
| 126 |
-
# - graph_embeddings.npy (~700KB)
|
| 127 |
-
# - node_to_idx.npy (~50KB)
|
| 128 |
-
```
|
| 129 |
-
|
| 130 |
-
### Step 5: Upload to Hugging Face
|
| 131 |
-
|
| 132 |
-
**Option A: Web Upload**
|
| 133 |
-
|
| 134 |
-
1. Go to your Space's Files tab
|
| 135 |
-
2. Click "Add file" → "Upload files"
|
| 136 |
-
3. Drag and drop all files
|
| 137 |
-
4. Commit changes
|
| 138 |
-
|
| 139 |
-
**Option B: Git Upload**
|
| 140 |
-
|
| 141 |
-
```bash
|
| 142 |
-
# Clone your space
|
| 143 |
-
git clone https://huggingface.co/spaces/YOUR_USERNAME/pharmacology-knowledge-graph
|
| 144 |
-
cd pharmacology-knowledge-graph
|
| 145 |
-
|
| 146 |
-
# Copy files
|
| 147 |
-
cp /path/to/pharmacology-graph/app.py .
|
| 148 |
-
cp /path/to/pharmacology-graph/requirements_app.txt requirements.txt
|
| 149 |
-
cp /path/to/pharmacology-graph/*.csv .
|
| 150 |
-
cp /path/to/pharmacology-graph/*.npy .
|
| 151 |
-
|
| 152 |
-
# Commit and push
|
| 153 |
-
git add .
|
| 154 |
-
git commit -m "Initial app deployment"
|
| 155 |
-
git push
|
| 156 |
-
```
|
| 157 |
-
|
| 158 |
-
### Step 6: Monitor Deployment
|
| 159 |
-
|
| 160 |
-
1. The Space will automatically build (takes ~2-3 minutes)
|
| 161 |
-
2. Check the build logs for errors
|
| 162 |
-
3. Once running, test the app with example drugs
|
| 163 |
-
|
| 164 |
-
### Step 7: Optional Enhancements
|
| 165 |
-
|
| 166 |
-
**Upgrade to GPU (for faster predictions):**
|
| 167 |
-
- Settings → Hardware → Upgrade to T4 small ($0.60/hour)
|
| 168 |
-
- Useful if computing predictions on-the-fly for new molecules
|
| 169 |
-
|
| 170 |
-
**Enable persistence:**
|
| 171 |
-
- Add a `cache/` directory for storing results
|
| 172 |
-
- Set `GRADIO_CACHE_EXAMPLES=True` in Space settings
|
| 173 |
-
|
| 174 |
-
**Add analytics:**
|
| 175 |
-
```python
|
| 176 |
-
# In app.py, add Hugging Face analytics
|
| 177 |
-
import os
|
| 178 |
-
from huggingface_hub import HfApi
|
| 179 |
-
|
| 180 |
-
# Track usage
|
| 181 |
-
api = HfApi()
|
| 182 |
-
```
|
| 183 |
-
|
| 184 |
-
### Troubleshooting
|
| 185 |
-
|
| 186 |
-
**"File not found" errors:**
|
| 187 |
-
- Make sure all CSV and NPY files are in the root directory
|
| 188 |
-
- Check file names match exactly (case-sensitive)
|
| 189 |
-
|
| 190 |
-
**Memory errors:**
|
| 191 |
-
- If embeddings are too large, upgrade to "CPU upgrade" ($0.03/hour)
|
| 192 |
-
- Or pre-compute all predictions and use lookup tables
|
| 193 |
-
|
| 194 |
-
**Slow loading:**
|
| 195 |
-
- Add caching: `@st.cache_data` (Streamlit) or `gr.State()` (Gradio)
|
| 196 |
-
- Pre-load data in global scope (already done in `app.py`)
|
| 197 |
-
|
| 198 |
-
### Cost Estimate
|
| 199 |
-
|
| 200 |
-
**Free tier (CPU basic):**
|
| 201 |
-
- ✅ Sufficient for this app
|
| 202 |
-
- 2 vCPU, 16GB RAM
|
| 203 |
-
- Always-on
|
| 204 |
-
|
| 205 |
-
**Paid tier (if needed):**
|
| 206 |
-
- CPU upgrade: $0.03/hour (~$22/month)
|
| 207 |
-
- T4 GPU: $0.60/hour (only if doing real-time SMILES predictions)
|
| 208 |
-
|
| 209 |
-
---
|
| 210 |
-
|
| 211 |
-
## 🎉 You're Done!
|
| 212 |
-
|
| 213 |
-
Your app should now be live at:
|
| 214 |
-
`https://huggingface.co/spaces/YOUR_USERNAME/pharmacology-knowledge-graph`
|
| 215 |
-
|
| 216 |
-
Share it with:
|
| 217 |
-
- Colleagues and collaborators
|
| 218 |
-
- On Twitter/LinkedIn with #DrugDiscovery #AI
|
| 219 |
-
- In your competition submission
|
| 220 |
-
|
| 221 |
-
Good luck! 🚀
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FILES.md
DELETED
|
@@ -1,214 +0,0 @@
|
|
| 1 |
-
# File Manifest - Pharmacology Graph
|
| 2 |
-
|
| 3 |
-
Quick reference for what each file does.
|
| 4 |
-
|
| 5 |
-
---
|
| 6 |
-
|
| 7 |
-
## 🚀 **ESSENTIAL FILES** (Keep These)
|
| 8 |
-
|
| 9 |
-
### Application Files
|
| 10 |
-
- **`app.py`** - Main Gradio web application (604 lines)
|
| 11 |
-
- **`requirements_app.txt`** - Python dependencies for the app
|
| 12 |
-
- **`start_app.sh`** - Launch script (recommended)
|
| 13 |
-
- **`test_app.py`** - Diagnostic test for data loading
|
| 14 |
-
|
| 15 |
-
### Data Files (Required)
|
| 16 |
-
- **`drug_nodes.csv`** - 3,127 approved drugs with SMILES structures
|
| 17 |
-
- **`protein_nodes_with_embeddings.csv`** - 1,156 protein targets
|
| 18 |
-
- **`drug_effects.csv`** - 8,312 clinical effects/indications
|
| 19 |
-
- **`drugs_interactions.csv`** - 11,703 known drug-protein interactions
|
| 20 |
-
- **`graph_embeddings.npy`** - Trained 128-dim TransE embeddings (5,201 nodes)
|
| 21 |
-
- **`node_to_idx.npy`** - Node ID to embedding index mapping
|
| 22 |
-
- **`top_50_predicted_drug_protein.csv`** - Top 50 predicted drug-target pairs
|
| 23 |
-
- **`top_50_predicted_drug_effects.csv`** - Top 50 predicted drug-effect pairs
|
| 24 |
-
|
| 25 |
-
### Documentation
|
| 26 |
-
- **`README.md`** - Project overview, results, and citations
|
| 27 |
-
- **`SETUP.md`** - Complete setup guide (START HERE!)
|
| 28 |
-
- **`DEPLOYMENT.md`** - Guide for deploying to Hugging Face Spaces
|
| 29 |
-
- **`APP_GUIDE.md`** - User guide for the web application
|
| 30 |
-
|
| 31 |
-
---
|
| 32 |
-
|
| 33 |
-
## 🔬 **DEVELOPMENT FILES** (Optional)
|
| 34 |
-
|
| 35 |
-
### Research Notebook
|
| 36 |
-
- **`code.ipynb`** - Main Jupyter notebook with full pipeline:
|
| 37 |
-
- Data extraction from ChEMBL
|
| 38 |
-
- ESM-2 protein embedding generation (~30 min GPU)
|
| 39 |
-
- TransE graph model training (100 epochs)
|
| 40 |
-
- Link prediction and validation
|
| 41 |
-
|
| 42 |
-
**Note**: Only needed if you want to retrain the model or explore the data processing pipeline.
|
| 43 |
-
|
| 44 |
-
### Full Dependencies
|
| 45 |
-
- **`requirements.txt`** - Complete dependencies (includes transformers, torch, rdkit)
|
| 46 |
-
- **Use this if**: You want to run `code.ipynb`
|
| 47 |
-
- **Skip if**: You just want to run the app (use `requirements_app.txt` instead)
|
| 48 |
-
|
| 49 |
-
### ChEMBL Database
|
| 50 |
-
- **`chembl_36/chembl_36_sqlite/chembl_36.db`** - Full ChEMBL 36 database (4.2GB)
|
| 51 |
-
- **Needed for**: Running `code.ipynb` to extract fresh data
|
| 52 |
-
- **Skip if**: You're using the pre-extracted CSV files
|
| 53 |
-
|
| 54 |
-
---
|
| 55 |
-
|
| 56 |
-
## 🗑️ **REMOVABLE FILES** (Can Delete)
|
| 57 |
-
|
| 58 |
-
### Duplicates/Old Versions
|
| 59 |
-
- `run_app.sh` - Old launch script (use `start_app.sh` instead)
|
| 60 |
-
- `APP_SUMMARY.md` - Duplicate of `APP_GUIDE.md`
|
| 61 |
-
- `CHECKLIST.md` - Deployment checklist (one-time use)
|
| 62 |
-
- `BUGFIX_SUMMARY.md` - Development notes about version fixes
|
| 63 |
-
|
| 64 |
-
### Testing Scripts
|
| 65 |
-
- `test_search.py` - Manual testing guide (not automated)
|
| 66 |
-
|
| 67 |
-
### Intermediate Files (Can Regenerate)
|
| 68 |
-
- `main.py` - Old/experimental code
|
| 69 |
-
- `.python-version` - Python version pin (use pyproject.toml instead)
|
| 70 |
-
- `*.png` - Visualization outputs (can regenerate from notebook)
|
| 71 |
-
- `*.pkl` - Pickle serializations (can regenerate from CSV)
|
| 72 |
-
- `drug_mechanism_filtered.csv` - Intermediate processing file
|
| 73 |
-
- `drug_warnings.csv` - Intermediate processing file
|
| 74 |
-
- `edges_drug_protein.csv` - Intermediate processing file
|
| 75 |
-
- `proteins_for_embedding.csv` - Intermediate processing file
|
| 76 |
-
- `top_50_predicted_drug_targets.csv` - Duplicate of `top_50_predicted_drug_protein.csv`
|
| 77 |
-
|
| 78 |
-
**Run cleanup script**: `./cleanup.sh` to remove these automatically.
|
| 79 |
-
|
| 80 |
-
---
|
| 81 |
-
|
| 82 |
-
## 📏 **FILE SIZES**
|
| 83 |
-
|
| 84 |
-
### App Files (~10 MB total)
|
| 85 |
-
```
|
| 86 |
-
drug_nodes.csv 700 KB
|
| 87 |
-
protein_nodes_with_embeddings.csv 400 KB
|
| 88 |
-
drug_effects.csv 800 KB
|
| 89 |
-
drugs_interactions.csv 1.5 MB
|
| 90 |
-
graph_embeddings.npy 5 MB
|
| 91 |
-
node_to_idx.npy 50 KB
|
| 92 |
-
top_50_predicted_*.csv 10 KB each
|
| 93 |
-
app.py 50 KB
|
| 94 |
-
```
|
| 95 |
-
|
| 96 |
-
### Development Files (4.2 GB)
|
| 97 |
-
```
|
| 98 |
-
chembl_36/chembl_36_sqlite/chembl_36.db 4.2 GB
|
| 99 |
-
code.ipynb 500 KB
|
| 100 |
-
```
|
| 101 |
-
|
| 102 |
-
---
|
| 103 |
-
|
| 104 |
-
## 🎯 **WHAT YOU NEED FOR...**
|
| 105 |
-
|
| 106 |
-
### Running the App Only
|
| 107 |
-
```
|
| 108 |
-
✓ app.py
|
| 109 |
-
✓ requirements_app.txt
|
| 110 |
-
✓ start_app.sh (or test_app.py)
|
| 111 |
-
✓ All CSV files
|
| 112 |
-
✓ graph_embeddings.npy
|
| 113 |
-
✓ node_to_idx.npy
|
| 114 |
-
✓ README.md, SETUP.md (for reference)
|
| 115 |
-
```
|
| 116 |
-
**Total**: ~10 MB
|
| 117 |
-
|
| 118 |
-
### Retraining the Model
|
| 119 |
-
```
|
| 120 |
-
✓ Everything from "Running the App"
|
| 121 |
-
✓ code.ipynb
|
| 122 |
-
✓ requirements.txt
|
| 123 |
-
✓ chembl_36/ directory (ChEMBL database)
|
| 124 |
-
```
|
| 125 |
-
**Total**: ~4.2 GB
|
| 126 |
-
|
| 127 |
-
### Deploying to Hugging Face Spaces
|
| 128 |
-
```
|
| 129 |
-
✓ app.py
|
| 130 |
-
✓ All CSV files
|
| 131 |
-
✓ graph_embeddings.npy
|
| 132 |
-
✓ node_to_idx.npy
|
| 133 |
-
✓ requirements_app.txt → rename to requirements.txt
|
| 134 |
-
✓ SPACE_README.md → use as README.md
|
| 135 |
-
```
|
| 136 |
-
**Total**: ~10 MB (HF Spaces free tier supports up to 50GB)
|
| 137 |
-
|
| 138 |
-
---
|
| 139 |
-
|
| 140 |
-
## 🧹 **CLEANUP COMMANDS**
|
| 141 |
-
|
| 142 |
-
### Remove all unnecessary files
|
| 143 |
-
```bash
|
| 144 |
-
./cleanup.sh
|
| 145 |
-
```
|
| 146 |
-
|
| 147 |
-
### Manual cleanup
|
| 148 |
-
```bash
|
| 149 |
-
# Remove duplicate documentation
|
| 150 |
-
rm -f BUGFIX_SUMMARY.md APP_SUMMARY.md CHECKLIST.md
|
| 151 |
-
|
| 152 |
-
# Remove old scripts
|
| 153 |
-
rm -f run_app.sh test_search.py main.py
|
| 154 |
-
|
| 155 |
-
# Remove generated outputs
|
| 156 |
-
rm -f *.png *.pkl
|
| 157 |
-
|
| 158 |
-
# Remove intermediate CSV files
|
| 159 |
-
rm -f drug_mechanism_filtered.csv drug_warnings.csv edges_drug_protein.csv proteins_for_embedding.csv
|
| 160 |
-
```
|
| 161 |
-
|
| 162 |
-
### Remove development files (if you don't need to retrain)
|
| 163 |
-
```bash
|
| 164 |
-
# Remove notebook and database (WARNING: Large files!)
|
| 165 |
-
rm -rf code.ipynb chembl_36/ requirements.txt
|
| 166 |
-
```
|
| 167 |
-
|
| 168 |
-
---
|
| 169 |
-
|
| 170 |
-
## 📦 **WHAT'S IN GIT**
|
| 171 |
-
|
| 172 |
-
The `.gitignore` is configured to:
|
| 173 |
-
|
| 174 |
-
**✅ Track:**
|
| 175 |
-
- All Python files (`*.py`)
|
| 176 |
-
- All CSV files (`*.csv`)
|
| 177 |
-
- All Jupyter notebooks (`*.ipynb`)
|
| 178 |
-
- Documentation (`*.md`)
|
| 179 |
-
- Config files (`requirements*.txt`, `pyproject.toml`)
|
| 180 |
-
|
| 181 |
-
**❌ Ignore:**
|
| 182 |
-
- Large binary files (`*.npy`, `*.pkl`, `*.db`)
|
| 183 |
-
- Images (`*.png`, `*.jpg`)
|
| 184 |
-
- Python cache (`__pycache__/`, `*.pyc`)
|
| 185 |
-
- Model checkpoints (`*.pth`, `*.pt`)
|
| 186 |
-
- Compressed files (`*.zip`, `*.tar.gz`)
|
| 187 |
-
|
| 188 |
-
**Why NPY files aren't tracked**: They're 5MB+ and can be regenerated from the notebook. Download them separately or run the notebook to create them.
|
| 189 |
-
|
| 190 |
-
---
|
| 191 |
-
|
| 192 |
-
## 🔄 **REGENERATING FILES**
|
| 193 |
-
|
| 194 |
-
If you're missing `.npy` files or want to retrain:
|
| 195 |
-
|
| 196 |
-
```bash
|
| 197 |
-
# Install full dependencies
|
| 198 |
-
pip install -r requirements.txt
|
| 199 |
-
|
| 200 |
-
# Open notebook
|
| 201 |
-
jupyter notebook code.ipynb
|
| 202 |
-
|
| 203 |
-
# Run all cells (takes ~40 minutes on GPU)
|
| 204 |
-
# This will regenerate:
|
| 205 |
-
# - All CSV files
|
| 206 |
-
# - graph_embeddings.npy
|
| 207 |
-
# - node_to_idx.npy
|
| 208 |
-
# - Prediction CSVs
|
| 209 |
-
```
|
| 210 |
-
|
| 211 |
-
---
|
| 212 |
-
|
| 213 |
-
**Last Updated**: October 10, 2025
|
| 214 |
-
**Total Project Size**: 4.2 GB (with database) or 10 MB (app only)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
README.md
CHANGED
|
@@ -1,415 +1,29 @@
|
|
| 1 |
---
|
| 2 |
-
title: Pharmacology
|
| 3 |
emoji: 💊
|
| 4 |
colorFrom: blue
|
| 5 |
colorTo: purple
|
| 6 |
-
sdk:
|
| 7 |
-
|
| 8 |
-
app_file: app.py
|
| 9 |
pinned: false
|
| 10 |
license: mit
|
| 11 |
-
python_version: "3.10"
|
| 12 |
---
|
| 13 |
|
| 14 |
-
# Pharmacology
|
| 15 |
|
| 16 |
-
|
|
|
|
|
|
|
|
|
|
| 17 |
|
| 18 |
-
**
|
|
|
|
| 19 |
|
| 20 |
-
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
```bash
|
| 25 |
-
# 1. Clone the repository
|
| 26 |
-
git clone https://github.com/JoeVonDahab/pharmacology-graph.git
|
| 27 |
-
cd pharmacology-graph
|
| 28 |
-
|
| 29 |
-
# 2. Install dependencies
|
| 30 |
-
pip install -r requirements_app.txt
|
| 31 |
-
|
| 32 |
-
# 3. Run the interactive app
|
| 33 |
-
./start_app.sh
|
| 34 |
-
# Open http://localhost:7860 in your browser
|
| 35 |
-
```
|
| 36 |
-
|
| 37 |
-
**Requirements**: Python 3.9+, 8GB RAM, 10MB disk space (app only)
|
| 38 |
-
|
| 39 |
-
For complete setup instructions and troubleshooting, see **[SETUP.md](SETUP.md)**.
|
| 40 |
-
|
| 41 |
-
---
|
| 42 |
-
|
| 43 |
-
## 🎯 Project Overview
|
| 44 |
-
|
| 45 |
-
This project builds an end-to-end pipeline that:
|
| 46 |
-
|
| 47 |
-
1. **Extracts pharmacological data** from ChEMBL database (approved drugs, protein targets, clinical effects)
|
| 48 |
-
2. **Generates molecular representations** using:
|
| 49 |
-
- ESM-2 protein language models (2560-dim embeddings)
|
| 50 |
-
- SMILES-based molecular fingerprints
|
| 51 |
-
3. **Trains a TransE graph embedding model** to align drugs, proteins, and clinical effects in a shared latent space
|
| 52 |
-
4. **Predicts novel interactions** using GPU-accelerated similarity search
|
| 53 |
-
|
| 54 |
-
### Key Innovation: Pharmacology-Aligned Embeddings
|
| 55 |
-
|
| 56 |
-
Unlike traditional chemical similarity (fingerprints) or docking approaches, our model learns embeddings where **drugs cluster by functional mechanism** rather than just structural similarity. For example:
|
| 57 |
-
|
| 58 |
-
- **Opioid analgesics** (Morphine, l) cluster together despite different structures
|
| 59 |
-
- **Antivirals** (Acyclovir, Famciclovir) group by shared viral DNA polymerase targets
|
| 60 |
-
- **Bronchodilators** (Tiotropium, Ipratropium) align based on muscarinic receptor activity
|
| 61 |
-
|
| 62 |
-
---
|
| 63 |
-
|
| 64 |
-
## 🏗️ Architecture
|
| 65 |
-
|
| 66 |
-
```
|
| 67 |
-
ChEMBL Database
|
| 68 |
-
↓
|
| 69 |
-
[Data Extraction]
|
| 70 |
-
├── Approved Drugs (SMILES)
|
| 71 |
-
├── Protein Targets (sequences)
|
| 72 |
-
└── Clinical Effects (indications)
|
| 73 |
-
↓
|
| 74 |
-
[Embedding Generation]
|
| 75 |
-
├── ESM-2 (facebook/esm2_t36_3B_UR50D) → Protein embeddings
|
| 76 |
-
└── Morgan Fingerprints → Drug structure features
|
| 77 |
-
↓
|
| 78 |
-
[Knowledge Graph Construction]
|
| 79 |
-
├── Nodes: Drugs, Proteins, Effects
|
| 80 |
-
└── Edges: binds_to, treats
|
| 81 |
-
↓
|
| 82 |
-
[TransE Training]
|
| 83 |
-
└── 128-dim unified embedding space
|
| 84 |
-
↓
|
| 85 |
-
[Link Prediction]
|
| 86 |
-
├── Drug → Protein (novel targets)
|
| 87 |
-
└── Drug → Effect (repurposing)
|
| 88 |
-
```
|
| 89 |
-
|
| 90 |
-
---
|
| 91 |
-
|
| 92 |
-
## 📊 Results
|
| 93 |
-
|
| 94 |
-
### Validation: Drug Clustering
|
| 95 |
-
|
| 96 |
-
The model successfully groups drugs by pharmacological class:
|
| 97 |
-
|
| 98 |
-
| Anchor Drug | Top Similar Drugs | Pharmacological Class |
|
| 99 |
-
|-------------|-------------------|----------------------|
|
| 100 |
-
| **Morphine** | l, Oxycodone, Hydromorphone | Opioid analgesics (μ-receptor) |
|
| 101 |
-
| **Acyclovir** | Famciclovir, Penciclovir, Valacyclovir | Nucleoside antiviral (DNA polymerase) |
|
| 102 |
-
| **Tiotropium** | Glycopyrronium, Ipratropium, Aclidinium | Anticholinergic bronchodilators (M3-receptor) |
|
| 103 |
-
| **Miconazole** | Posaconazole, Ketoconazole | Azole antifungals (CYP51A1) |
|
| 104 |
-
|
| 105 |
-
**Mean cosine similarity:**
|
| 106 |
-
- Within therapeutic class: **0.72 ± 0.08**
|
| 107 |
-
- Between classes: **0.31 ± 0.12**
|
| 108 |
-
|
| 109 |
-
### Top Predicted Drug-Target Interactions
|
| 110 |
-
|
| 111 |
-
From **2.8M novel predictions**, top examples with biological validation:
|
| 112 |
-
|
| 113 |
-
| Drug | Predicted Target | Similarity | Biological Rationale |
|
| 114 |
-
|------|-----------------|------------|---------------------|
|
| 115 |
-
| **Talazoparib** | Protein mono-ADP-ribosyltransferase (PARP3/4) | 0.60 | ✅ Known PARP1/2 inhibitor; homologous family members |
|
| 116 |
-
| **Dasatinib** | Blk tyrosine kinase | 0.51 | ✅ Broad-spectrum Src-family kinase inhibitor |
|
| 117 |
-
| **Imipramine** | α1D adrenergic receptor | 0.52 | ✅ Tricyclic with known adrenergic off-targets |
|
| 118 |
-
| **Zonisamide** | Carbonic anhydrase 14 | 0.51 | ✅ Known CA inhibitory activity |
|
| 119 |
-
| **Pipamazine** | Muscarinic M4 receptor | 0.54 | ✅ Phenothiazine with anticholinergic effects |
|
| 120 |
-
|
| 121 |
-
### Top Predicted Drug-Effect (Repurposing Candidates)
|
| 122 |
-
|
| 123 |
-
| Drug | Predicted Indication | Similarity | Clinical Plausibility |
|
| 124 |
-
|------|---------------------|------------|---------------------|
|
| 125 |
-
| **Rivaroxaban** | Myocardial infarction (secondary prevention) | 0.54 | ✅ Anticoagulant; approved for post-MI use |
|
| 126 |
-
| **Sertraline** | Panic disorder | 0.53 | ✅ FDA-approved indication |
|
| 127 |
-
| **Rosuvastatin** | Dyslipidemias | 0.52 | ✅ Primary statin indication |
|
| 128 |
-
| **Ozanimod** | Crohn's disease | 0.49 | ⚠️ Plausible (approved for ulcerative colitis) |
|
| 129 |
-
| **Clopidogrel** | Pulmonary embolism | 0.49 | ⚠️ Antiplatelet; not first-line but mechanistically coherent |
|
| 130 |
-
|
| 131 |
-
**Precision metrics:**
|
| 132 |
-
- Top-50 predictions: **~90% pharmacologically coherent**
|
| 133 |
-
- Mean similarity (novel predictions): **0.48 ± 0.05**
|
| 134 |
-
- Baseline (random pairing): **0.23 ± 0.11**
|
| 135 |
-
|
| 136 |
-
---
|
| 137 |
-
|
| 138 |
-
## 🚀 Quick Start
|
| 139 |
-
|
| 140 |
-
### Requirements
|
| 141 |
-
|
| 142 |
-
```bash
|
| 143 |
-
# Install dependencies with UV
|
| 144 |
-
uv pip install -r requirements.txt
|
| 145 |
-
|
| 146 |
-
# Core dependencies:
|
| 147 |
-
- pandas
|
| 148 |
-
- numpy
|
| 149 |
-
- torch
|
| 150 |
-
- transformers (ESM-2)
|
| 151 |
-
- rdkit
|
| 152 |
-
- networkx
|
| 153 |
-
- scikit-learn
|
| 154 |
-
- tqdm
|
| 155 |
-
- matplotlib
|
| 156 |
-
```
|
| 157 |
-
|
| 158 |
-
### Data
|
| 159 |
-
|
| 160 |
-
Download ChEMBL 36 SQLite database:
|
| 161 |
-
```bash
|
| 162 |
-
# Place in: chembl_36/chembl_36_sqlite/chembl_36.db
|
| 163 |
-
# Size: ~4.2 GB
|
| 164 |
-
```
|
| 165 |
-
|
| 166 |
-
### Run the Pipeline
|
| 167 |
-
|
| 168 |
-
```bash
|
| 169 |
-
# Open the Jupyter notebook
|
| 170 |
-
jupyter notebook code.ipynb
|
| 171 |
-
|
| 172 |
-
# Or run as Python script (convert cells first)
|
| 173 |
-
jupyter nbconvert --to script code.ipynb
|
| 174 |
-
python code.py
|
| 175 |
-
```
|
| 176 |
-
|
| 177 |
-
**Pipeline stages:**
|
| 178 |
-
|
| 179 |
-
1. **Data extraction** (cells 1-14): Query ChEMBL for drugs, targets, effects
|
| 180 |
-
2. **Protein embeddings** (cells 15-18): Generate ESM-2 embeddings (GPU recommended, ~30 min)
|
| 181 |
-
3. **Graph construction** (cells 19-35): Build NetworkX graph with nodes/edges
|
| 182 |
-
4. **TransE training** (cell 36): Train embedding model (100 epochs, ~15 min on GPU)
|
| 183 |
-
5. **Prediction** (cells 37-42): Generate novel drug-target and drug-effect predictions
|
| 184 |
-
6. **Visualization** (cells 43-45): t-SNE plots, neighbor analysis
|
| 185 |
-
|
| 186 |
-
---
|
| 187 |
-
|
| 188 |
-
## 📁 Project Structure
|
| 189 |
-
|
| 190 |
-
```
|
| 191 |
-
pharmacology-graph/
|
| 192 |
-
├── code.ipynb # Main analysis notebook
|
| 193 |
-
├── README.md # This file
|
| 194 |
-
├── .gitignore # Git ignore rules
|
| 195 |
-
├── requirements.txt # Python dependencies (UV)
|
| 196 |
-
│
|
| 197 |
-
├── chembl_36/
|
| 198 |
-
│ └── chembl_36_sqlite/
|
| 199 |
-
│ └── chembl_36.db # ChEMBL database (not in git)
|
| 200 |
-
│
|
| 201 |
-
├── protein_nodes_with_embeddings.pkl # ESM-2 protein embeddings (not in git)
|
| 202 |
-
├── drug_nodes.pkl # Drug metadata (not in git)
|
| 203 |
-
├── drug_effects.pkl # Drug-indication mappings (not in git)
|
| 204 |
-
├── drug_protein_interactions.pkl # Known drug-target edges (not in git)
|
| 205 |
-
│
|
| 206 |
-
├── graph_embeddings.npy # Trained TransE embeddings (not in git)
|
| 207 |
-
├── node_to_idx.npy # Node index mapping (not in git)
|
| 208 |
-
│
|
| 209 |
-
├── top_50_predicted_drug_protein.csv # Novel target predictions
|
| 210 |
-
├── top_50_predicted_drug_effects.csv # Novel indication predictions
|
| 211 |
-
└── drug_neighbors_visualization.png # t-SNE cluster plot (not in git)
|
| 212 |
-
```
|
| 213 |
-
|
| 214 |
-
---
|
| 215 |
-
|
| 216 |
-
## 🔬 Technical Details
|
| 217 |
-
|
| 218 |
-
### Model Architecture: TransE
|
| 219 |
-
|
| 220 |
-
**TranslatingEmbeddings for Multi-Relational Graphs**
|
| 221 |
-
|
| 222 |
-
For each edge `(head, relation, tail)`:
|
| 223 |
-
- **Scoring function:** `f(h, r, t) = ||h + r - t||₂`
|
| 224 |
-
- **Loss:** Margin-based ranking loss with negative sampling
|
| 225 |
-
|
| 226 |
-
**Hyperparameters:**
|
| 227 |
-
```python
|
| 228 |
-
EMBEDDING_DIM = 128
|
| 229 |
-
LEARNING_RATE = 0.01
|
| 230 |
-
EPOCHS = 100
|
| 231 |
-
BATCH_SIZE = 32
|
| 232 |
-
MARGIN = 1.0
|
| 233 |
-
```
|
| 234 |
-
|
| 235 |
-
**Training stats:**
|
| 236 |
-
- Nodes: ~1,400 (drugs: ~800, proteins: ~200, effects: ~400)
|
| 237 |
-
- Edges: ~15,000 (drug-protein: ~12,000, drug-effect: ~3,000)
|
| 238 |
-
- Training time: 15 minutes (NVIDIA GPU)
|
| 239 |
-
- Final loss: ~0.15
|
| 240 |
-
|
| 241 |
-
### ESM-2 Protein Embeddings
|
| 242 |
-
|
| 243 |
-
**Model:** `facebook/esm2_t36_3B_UR50D`
|
| 244 |
-
- Parameters: 3B
|
| 245 |
-
- Embedding dimension: 2560
|
| 246 |
-
- Context length: 1024 amino acids
|
| 247 |
-
- Mean pooling over sequence length
|
| 248 |
|
| 249 |
-
|
| 250 |
-
-
|
| 251 |
-
- Total proteins: ~200
|
| 252 |
-
- Compute time: ~30 minutes (GPU) / ~3 hours (CPU)
|
| 253 |
-
|
| 254 |
-
### Drug Representations
|
| 255 |
-
|
| 256 |
-
**SMILES → Morgan Fingerprints**
|
| 257 |
-
```python
|
| 258 |
-
radius = 2
|
| 259 |
-
n_bits = 2048
|
| 260 |
-
```
|
| 261 |
-
|
| 262 |
-
**Bridge to Graph Embeddings:**
|
| 263 |
-
- Ridge regression: Fingerprint → TransE embedding
|
| 264 |
-
- R² score: 0.67 (on training drugs)
|
| 265 |
-
- Enables predictions for completely novel molecules
|
| 266 |
-
|
| 267 |
-
---
|
| 268 |
-
|
| 269 |
-
## 🧪 Validation Strategy
|
| 270 |
-
|
| 271 |
-
### 1. **Held-out Known Interactions**
|
| 272 |
-
|
| 273 |
-
Split known drug-target edges:
|
| 274 |
-
- Train: 80% (used for TransE)
|
| 275 |
-
- Test: 20% (hidden during training)
|
| 276 |
-
|
| 277 |
-
**Metrics:**
|
| 278 |
-
- Recall@50: How many true targets appear in top-50 predictions?
|
| 279 |
-
- Mean Reciprocal Rank (MRR)
|
| 280 |
-
- AUROC for ranked predictions
|
| 281 |
-
|
| 282 |
-
### 2. **Time-based Split**
|
| 283 |
-
|
| 284 |
-
- Train on: Drug approvals ≤ 2015
|
| 285 |
-
- Test on: Approvals > 2015
|
| 286 |
-
- Simulates prospective prediction
|
| 287 |
-
|
| 288 |
-
### 3. **Baseline Comparisons**
|
| 289 |
-
|
| 290 |
-
| Method | Recall@50 | MRR | AUROC |
|
| 291 |
-
|--------|-----------|-----|-------|
|
| 292 |
-
| **Our Model (TransE)** | 0.68 | 0.42 | 0.83 |
|
| 293 |
-
| ECFP Tanimoto (fingerprint) | 0.31 | 0.18 | 0.67 |
|
| 294 |
-
| Random baseline | 0.02 | 0.01 | 0.50 |
|
| 295 |
-
|
| 296 |
-
**Ablation studies:**
|
| 297 |
-
- Without ESM-2 (random protein init): -0.15 AUROC
|
| 298 |
-
- Without contrastive training: -0.11 AUROC
|
| 299 |
-
|
| 300 |
-
---
|
| 301 |
-
|
| 302 |
-
## 📈 Use Cases
|
| 303 |
-
|
| 304 |
-
### 1. **Drug Repurposing**
|
| 305 |
-
|
| 306 |
-
Find new therapeutic uses for approved drugs:
|
| 307 |
-
|
| 308 |
-
```python
|
| 309 |
-
# Example: Query novel indications for Aspirin
|
| 310 |
-
drug_smiles = "CC(=O)Oc1ccccc1C(=O)O" # Aspirin
|
| 311 |
-
predictions = predict_new_drug_embedding(drug_smiles, top_k=10)
|
| 312 |
-
|
| 313 |
-
# Output: Predicted new effects beyond pain/inflammation
|
| 314 |
-
# - Cardiovascular prevention (known)
|
| 315 |
-
# - Colorectal cancer prevention (emerging evidence)
|
| 316 |
-
```
|
| 317 |
-
|
| 318 |
-
### 2. **Target Identification**
|
| 319 |
-
|
| 320 |
-
Predict protein targets for experimental compounds:
|
| 321 |
-
|
| 322 |
-
```python
|
| 323 |
-
# Novel kinase inhibitor candidate
|
| 324 |
-
novel_smiles = "Cc1ccc(Nc2nccc(...)...)cc1"
|
| 325 |
-
targets = predict_protein_targets(novel_smiles, top_k=20)
|
| 326 |
-
|
| 327 |
-
# Helps prioritize biochemical assays
|
| 328 |
-
```
|
| 329 |
-
|
| 330 |
-
### 3. **Off-target Prediction**
|
| 331 |
-
|
| 332 |
-
Identify safety liabilities early:
|
| 333 |
-
|
| 334 |
-
```python
|
| 335 |
-
# Check for unintended receptor binding
|
| 336 |
-
all_targets = predict_all_targets(drug_smiles, threshold=0.45)
|
| 337 |
-
safety_flags = [t for t in all_targets if t in ['hERG', 'CYP3A4', 'Opioid']]
|
| 338 |
-
```
|
| 339 |
-
|
| 340 |
-
---
|
| 341 |
-
|
| 342 |
-
## 🎓 Scientific Contributions
|
| 343 |
-
|
| 344 |
-
1. **Cross-modal contrastive learning** for drug discovery
|
| 345 |
-
- First work aligning SMILES + ESM-2 in shared space
|
| 346 |
-
|
| 347 |
-
2. **Pharmacology-aligned embeddings**
|
| 348 |
-
- Cluster by mechanism, not just structure
|
| 349 |
-
- Enables interpretable predictions
|
| 350 |
-
|
| 351 |
-
3. **Scalable graph-based prediction**
|
| 352 |
-
- Handles multi-relational heterogeneous graphs
|
| 353 |
-
- GPU-accelerated inference (~1M predictions/sec)
|
| 354 |
-
|
| 355 |
-
4. **Validated on real-world pharmacology**
|
| 356 |
-
- Recovers known drug classes (opioids, antivirals, statins)
|
| 357 |
-
- Predicts plausible novel targets with >80% precision
|
| 358 |
-
|
| 359 |
-
---
|
| 360 |
-
|
| 361 |
-
## 📝 Citation
|
| 362 |
-
|
| 363 |
-
```bibtex
|
| 364 |
-
@software{pharmacology_graph_2025,
|
| 365 |
-
author = {Joe VonDahab},
|
| 366 |
-
title = {Pharmacology Knowledge Graph: Drug-Target-Effect Prediction},
|
| 367 |
-
year = {2025},
|
| 368 |
-
url = {https://github.com/JoeVonDahab/pharmacology-graph}
|
| 369 |
-
}
|
| 370 |
-
```
|
| 371 |
-
|
| 372 |
-
**Related work:**
|
| 373 |
-
- **TransE:** Bordes et al., "Translating Embeddings for Modeling Multi-relational Data" (NeurIPS 2013)
|
| 374 |
-
- **ESM-2:** Lin et al., "Evolutionary-scale prediction of atomic-level protein structure" (Science 2023)
|
| 375 |
-
- **ChEMBL:** Gaulton et al., "The ChEMBL database in 2017" (Nucleic Acids Research 2017)
|
| 376 |
-
|
| 377 |
-
---
|
| 378 |
-
|
| 379 |
-
## 🤝 Contributing
|
| 380 |
-
|
| 381 |
-
Contributions welcome! Areas for improvement:
|
| 382 |
-
|
| 383 |
-
- [ ] Add attention-based graph neural network (GAT/RGCN)
|
| 384 |
-
- [ ] Incorporate 3D protein structures (AlphaFold2)
|
| 385 |
-
- [ ] Multi-task learning (toxicity + efficacy)
|
| 386 |
-
- [ ] Temporal dynamics (drug resistance evolution)
|
| 387 |
-
- [ ] Web interface (Streamlit/Gradio demo)
|
| 388 |
-
|
| 389 |
-
---
|
| 390 |
-
|
| 391 |
-
## 📄 License
|
| 392 |
-
|
| 393 |
-
MIT License - see LICENSE file for details
|
| 394 |
-
|
| 395 |
-
---
|
| 396 |
-
|
| 397 |
-
## 🙏 Acknowledgments
|
| 398 |
-
|
| 399 |
-
- **ChEMBL** for curated pharmacological data
|
| 400 |
-
- **Meta AI** for ESM-2 protein language models
|
| 401 |
-
- **RDKit** for cheminformatics tools
|
| 402 |
-
- **PyTorch** ecosystem for deep learning infrastructure
|
| 403 |
-
|
| 404 |
-
---
|
| 405 |
-
|
| 406 |
-
## 📧 Contact
|
| 407 |
-
|
| 408 |
-
**Author:** Youssef Abo-Dahab
|
| 409 |
-
**Repository:** [github.com/JoeVonDahab/pharmacology-graph](https://github.com/JoeVonDahab/pharmacology-graph)
|
| 410 |
-
|
| 411 |
-
For questions or collaboration: [create an issue](https://github.com/JoeVonDahab/pharmacology-graph/issues)
|
| 412 |
-
|
| 413 |
-
---
|
| 414 |
|
| 415 |
-
|
|
|
|
| 1 |
---
|
| 2 |
+
title: Pharmacology Graph Explorer
|
| 3 |
emoji: 💊
|
| 4 |
colorFrom: blue
|
| 5 |
colorTo: purple
|
| 6 |
+
sdk: static
|
| 7 |
+
app_file: index.html
|
|
|
|
| 8 |
pinned: false
|
| 9 |
license: mit
|
|
|
|
| 10 |
---
|
| 11 |
|
| 12 |
+
# Pharmacology Graph Explorer
|
| 13 |
|
| 14 |
+
Interactive explorer for the **Ablation 2 "No Drug Graphs"** model (~3.29M params) from
|
| 15 |
+
*pharmacology-graph* — learnable drug embeddings + ESM-2 protein representations + heterogeneous
|
| 16 |
+
GraphSAGE message passing. Removing the GAT drug-structure encoder *improved* drug–protein
|
| 17 |
+
prediction (PR-AUC 0.5631 → 0.5785) while cutting memory 5.30 GB → 353 MB.
|
| 18 |
|
| 19 |
+
Search a **drug** to see predicted targets & indications, or an **indication / protein** to see the
|
| 20 |
+
drugs most likely linked to it — each flagged *known* or *novel*.
|
| 21 |
|
| 22 |
+
A static front-end. Prediction data is served from the project's GitHub Pages
|
| 23 |
+
(<https://joevondahab.github.io/pharmacology-graph/>), so this Space and the Pages site share one
|
| 24 |
+
source of truth.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
|
| 26 |
+
- Code & notebooks: <https://github.com/JoeVonDahab/pharmacology-graph>
|
| 27 |
+
- Paper: <https://arxiv.org/abs/2603.01537>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
|
| 29 |
+
Predictions are model outputs for research exploration only — not clinical or experimental validation.
|
SETUP.md
DELETED
|
@@ -1,351 +0,0 @@
|
|
| 1 |
-
# Setup Guide - Pharmacology Knowledge Graph
|
| 2 |
-
|
| 3 |
-
Complete guide for setting up and running the Pharmacology Graph Explorer on your local machine.
|
| 4 |
-
|
| 5 |
-
---
|
| 6 |
-
|
| 7 |
-
## 📋 Prerequisites
|
| 8 |
-
|
| 9 |
-
- **Python**: 3.9 or higher
|
| 10 |
-
- **RAM**: At least 8GB (16GB recommended for large datasets)
|
| 11 |
-
- **Disk Space**: ~5GB for ChEMBL database and model files
|
| 12 |
-
|
| 13 |
-
---
|
| 14 |
-
|
| 15 |
-
## 🚀 Quick Start (3 Steps)
|
| 16 |
-
|
| 17 |
-
### 1. Clone the Repository
|
| 18 |
-
|
| 19 |
-
```bash
|
| 20 |
-
git clone https://github.com/JoeVonDahab/pharmacology-graph.git
|
| 21 |
-
cd pharmacology-graph
|
| 22 |
-
```
|
| 23 |
-
|
| 24 |
-
### 2. Install Dependencies
|
| 25 |
-
|
| 26 |
-
**Option A: Using `uv` (Recommended - Fast)**
|
| 27 |
-
```bash
|
| 28 |
-
# Install uv if you don't have it
|
| 29 |
-
pip install uv
|
| 30 |
-
|
| 31 |
-
# Install project dependencies
|
| 32 |
-
uv pip install -r requirements_app.txt
|
| 33 |
-
```
|
| 34 |
-
|
| 35 |
-
**Option B: Using `pip`**
|
| 36 |
-
```bash
|
| 37 |
-
pip install -r requirements_app.txt
|
| 38 |
-
```
|
| 39 |
-
|
| 40 |
-
**Critical Version Note**: Make sure you have:
|
| 41 |
-
- `gradio>=4.44.0` (not 4.36.x)
|
| 42 |
-
- `numpy<2.0` (NumPy 2.x breaks compatibility)
|
| 43 |
-
|
| 44 |
-
### 3. Run the App
|
| 45 |
-
|
| 46 |
-
```bash
|
| 47 |
-
./start_app.sh
|
| 48 |
-
```
|
| 49 |
-
|
| 50 |
-
Or manually:
|
| 51 |
-
```bash
|
| 52 |
-
python app.py
|
| 53 |
-
```
|
| 54 |
-
|
| 55 |
-
Then open your browser to: **http://localhost:7860**
|
| 56 |
-
|
| 57 |
-
---
|
| 58 |
-
|
| 59 |
-
## 📦 What's Included
|
| 60 |
-
|
| 61 |
-
### Essential Files (Required to Run)
|
| 62 |
-
|
| 63 |
-
| File | Purpose | Size |
|
| 64 |
-
|------|---------|------|
|
| 65 |
-
| `app.py` | Main Gradio web application | 604 lines |
|
| 66 |
-
| `requirements_app.txt` | Python dependencies | - |
|
| 67 |
-
| `start_app.sh` | Convenience launcher script | - |
|
| 68 |
-
|
| 69 |
-
### Data Files (Required to Run)
|
| 70 |
-
|
| 71 |
-
All these CSV files are **required** for the app to work:
|
| 72 |
-
|
| 73 |
-
| File | Description | Rows |
|
| 74 |
-
|------|-------------|------|
|
| 75 |
-
| `drug_nodes.csv` | Drug metadata (name, SMILES, ChEMBL ID) | 3,127 |
|
| 76 |
-
| `protein_nodes_with_embeddings.csv` | Protein targets with ESM-2 features | 1,156 |
|
| 77 |
-
| `drug_effects.csv` | Clinical effects and indications | 8,312 |
|
| 78 |
-
| `drugs_interactions.csv` | Known drug-protein interactions | 11,703 |
|
| 79 |
-
| `graph_embeddings.npy` | Trained TransE embeddings (128-dim) | 5,201 nodes |
|
| 80 |
-
| `node_to_idx.npy` | Node ID mappings | - |
|
| 81 |
-
| `top_50_predicted_drug_protein.csv` | Top predicted drug-target pairs | 50 |
|
| 82 |
-
| `top_50_predicted_drug_effects.csv` | Top predicted drug-effect pairs | 50 |
|
| 83 |
-
|
| 84 |
-
**Note**: The `.npy` files are NOT tracked in git (they're large). You need to generate them by running the notebook.
|
| 85 |
-
|
| 86 |
-
### Documentation Files
|
| 87 |
-
|
| 88 |
-
| File | Purpose |
|
| 89 |
-
|------|---------|
|
| 90 |
-
| `README.md` | Project overview and results |
|
| 91 |
-
| `DEPLOYMENT.md` | Guide for deploying to Hugging Face Spaces |
|
| 92 |
-
| `APP_GUIDE.md` | User guide for the web application |
|
| 93 |
-
| `BUGFIX_SUMMARY.md` | Recent bug fixes (version compatibility) |
|
| 94 |
-
|
| 95 |
-
### Development Files
|
| 96 |
-
|
| 97 |
-
| File | Purpose |
|
| 98 |
-
|------|---------|
|
| 99 |
-
| `code.ipynb` | Main research notebook (data extraction, training, prediction) |
|
| 100 |
-
| `requirements.txt` | Full dependencies for running the notebook |
|
| 101 |
-
| `test_app.py` | Diagnostic test for app data loading |
|
| 102 |
-
| `test_search.py` | Manual testing guide for search functionality |
|
| 103 |
-
|
| 104 |
-
---
|
| 105 |
-
|
| 106 |
-
## 🔄 Full Setup (If You Want to Retrain the Model)
|
| 107 |
-
|
| 108 |
-
If you want to regenerate the embeddings and predictions from scratch:
|
| 109 |
-
|
| 110 |
-
### 1. Download ChEMBL Database
|
| 111 |
-
|
| 112 |
-
```bash
|
| 113 |
-
# The ChEMBL 36 database is large (~4.2GB)
|
| 114 |
-
# It's already in chembl_36/chembl_36_sqlite/chembl_36.db
|
| 115 |
-
# If missing, download from: https://ftp.ebi.ac.uk/pub/databases/chembl/ChEMBLdb/latest/
|
| 116 |
-
```
|
| 117 |
-
|
| 118 |
-
### 2. Install Full Dependencies
|
| 119 |
-
|
| 120 |
-
```bash
|
| 121 |
-
pip install -r requirements.txt
|
| 122 |
-
```
|
| 123 |
-
|
| 124 |
-
This includes:
|
| 125 |
-
- `transformers` (for ESM-2 protein embeddings)
|
| 126 |
-
- `torch` (for TransE training)
|
| 127 |
-
- `rdkit` (for molecular fingerprints)
|
| 128 |
-
- `sqlite3` (for ChEMBL database queries)
|
| 129 |
-
|
| 130 |
-
### 3. Run the Notebook
|
| 131 |
-
|
| 132 |
-
Open `code.ipynb` in Jupyter and run all cells:
|
| 133 |
-
|
| 134 |
-
```bash
|
| 135 |
-
jupyter notebook code.ipynb
|
| 136 |
-
```
|
| 137 |
-
|
| 138 |
-
This will:
|
| 139 |
-
1. Extract data from ChEMBL (drugs, proteins, effects)
|
| 140 |
-
2. Generate ESM-2 embeddings for proteins (~30 min on GPU)
|
| 141 |
-
3. Train TransE graph model (100 epochs, ~10 min)
|
| 142 |
-
4. Generate predictions using cosine similarity
|
| 143 |
-
5. Export all CSV and NPY files
|
| 144 |
-
|
| 145 |
-
---
|
| 146 |
-
|
| 147 |
-
## 🧪 Testing the App
|
| 148 |
-
|
| 149 |
-
### Quick Test
|
| 150 |
-
|
| 151 |
-
```bash
|
| 152 |
-
python test_app.py
|
| 153 |
-
```
|
| 154 |
-
|
| 155 |
-
This checks:
|
| 156 |
-
- ✓ All data files are present
|
| 157 |
-
- ✓ Libraries are correctly installed
|
| 158 |
-
- ✓ Search function works
|
| 159 |
-
- ✓ Data structure is valid
|
| 160 |
-
|
| 161 |
-
### Manual Testing
|
| 162 |
-
|
| 163 |
-
1. Start the app: `./start_app.sh`
|
| 164 |
-
2. Open: http://localhost:7860
|
| 165 |
-
3. Search for: "Aspirin", "Morphine", or "Imatinib"
|
| 166 |
-
4. Verify:
|
| 167 |
-
- Dropdown shows matching results
|
| 168 |
-
- Selecting a drug displays data tables
|
| 169 |
-
- Network visualization renders correctly
|
| 170 |
-
- No errors in console
|
| 171 |
-
|
| 172 |
-
---
|
| 173 |
-
|
| 174 |
-
## 🐛 Troubleshooting
|
| 175 |
-
|
| 176 |
-
### Port Already in Use
|
| 177 |
-
|
| 178 |
-
```bash
|
| 179 |
-
# Kill existing app instance
|
| 180 |
-
pkill -f "python.*app.py"
|
| 181 |
-
|
| 182 |
-
# Or use a different port
|
| 183 |
-
GRADIO_SERVER_PORT=7861 python app.py
|
| 184 |
-
```
|
| 185 |
-
|
| 186 |
-
### Import Errors
|
| 187 |
-
|
| 188 |
-
```bash
|
| 189 |
-
# Check gradio version (must be >=4.44.0)
|
| 190 |
-
pip show gradio
|
| 191 |
-
|
| 192 |
-
# Check numpy version (must be <2.0)
|
| 193 |
-
pip show numpy
|
| 194 |
-
|
| 195 |
-
# Reinstall with correct versions
|
| 196 |
-
pip install --force-reinstall "gradio>=4.44.0" "numpy<2.0"
|
| 197 |
-
```
|
| 198 |
-
|
| 199 |
-
### Missing Data Files
|
| 200 |
-
|
| 201 |
-
If you see errors about missing CSV files:
|
| 202 |
-
1. Make sure you cloned the full repository
|
| 203 |
-
2. Run `code.ipynb` to regenerate data files
|
| 204 |
-
3. Check `.gitignore` - some large files aren't tracked
|
| 205 |
-
|
| 206 |
-
### Search Not Showing Results
|
| 207 |
-
|
| 208 |
-
Make sure you:
|
| 209 |
-
1. Updated to Gradio 4.44+ (older versions have bugs)
|
| 210 |
-
2. Refreshed your browser after restarting the app
|
| 211 |
-
3. Check console for debug output (should show "Search 'xxx' found N results")
|
| 212 |
-
|
| 213 |
-
---
|
| 214 |
-
|
| 215 |
-
## 📊 Understanding the Output
|
| 216 |
-
|
| 217 |
-
### When You Search for a Drug
|
| 218 |
-
|
| 219 |
-
**Example: Searching "Aspirin"**
|
| 220 |
-
|
| 221 |
-
You'll see:
|
| 222 |
-
1. **Basic Info**: ChEMBL ID, SMILES structure
|
| 223 |
-
2. **Known Targets**: Proteins with measured pChEMBL values
|
| 224 |
-
3. **Predicted Targets**: Novel protein interactions (cosine similarity >0.7)
|
| 225 |
-
4. **Clinical Effects**: Known indications and phases
|
| 226 |
-
5. **Predicted Effects**: Potential repurposing opportunities
|
| 227 |
-
6. **Network Graph**: Interactive visualization of relationships
|
| 228 |
-
|
| 229 |
-
### Interpreting Predictions
|
| 230 |
-
|
| 231 |
-
- **Similarity Score**: 0.0-1.0 (higher = more confident)
|
| 232 |
-
- >0.8: Very high confidence
|
| 233 |
-
- 0.7-0.8: High confidence
|
| 234 |
-
- 0.6-0.7: Moderate confidence
|
| 235 |
-
- <0.6: Low confidence (not shown)
|
| 236 |
-
|
| 237 |
-
- **Confidence**: "Very High", "High", "Medium" based on similarity threshold
|
| 238 |
-
|
| 239 |
-
---
|
| 240 |
-
|
| 241 |
-
## 🚢 Deploying to Hugging Face Spaces
|
| 242 |
-
|
| 243 |
-
See `DEPLOYMENT.md` for complete step-by-step guide.
|
| 244 |
-
|
| 245 |
-
**Quick version:**
|
| 246 |
-
|
| 247 |
-
1. Create a Space at https://huggingface.co/spaces
|
| 248 |
-
2. Upload these files:
|
| 249 |
-
- `app.py`
|
| 250 |
-
- All CSV files
|
| 251 |
-
- `graph_embeddings.npy` and `node_to_idx.npy`
|
| 252 |
-
- Rename `requirements_app.txt` → `requirements.txt`
|
| 253 |
-
- Use `SPACE_README.md` content for README.md
|
| 254 |
-
3. Wait 2-3 minutes for build
|
| 255 |
-
4. Your app will be live!
|
| 256 |
-
|
| 257 |
-
---
|
| 258 |
-
|
| 259 |
-
## 🗑️ Unnecessary Files (Can Be Deleted)
|
| 260 |
-
|
| 261 |
-
**For end users who just want to run the app:**
|
| 262 |
-
|
| 263 |
-
You can safely delete:
|
| 264 |
-
- `BUGFIX_SUMMARY.md` (development notes)
|
| 265 |
-
- `APP_SUMMARY.md` (duplicate of APP_GUIDE.md)
|
| 266 |
-
- `CHECKLIST.md` (deployment checklist)
|
| 267 |
-
- `run_app.sh` (use `start_app.sh` instead)
|
| 268 |
-
- `test_search.py` (manual testing guide, not needed if app works)
|
| 269 |
-
- `requirements.txt` (only needed for notebook, use `requirements_app.txt`)
|
| 270 |
-
|
| 271 |
-
**If you're NOT retraining the model:**
|
| 272 |
-
- `code.ipynb` (the notebook)
|
| 273 |
-
- `chembl_36/` directory (large database)
|
| 274 |
-
- `full database.xml` (if present)
|
| 275 |
-
|
| 276 |
-
**Keep these minimal files:**
|
| 277 |
-
```
|
| 278 |
-
pharmacology-graph/
|
| 279 |
-
├── app.py
|
| 280 |
-
├── requirements_app.txt
|
| 281 |
-
├── start_app.sh
|
| 282 |
-
├── test_app.py
|
| 283 |
-
├── README.md
|
| 284 |
-
├── DEPLOYMENT.md
|
| 285 |
-
├── APP_GUIDE.md
|
| 286 |
-
├── *.csv (all CSV files)
|
| 287 |
-
├── graph_embeddings.npy
|
| 288 |
-
└── node_to_idx.npy
|
| 289 |
-
```
|
| 290 |
-
|
| 291 |
-
---
|
| 292 |
-
|
| 293 |
-
## 📝 File Size Reference
|
| 294 |
-
|
| 295 |
-
```
|
| 296 |
-
drug_nodes.csv ~700 KB
|
| 297 |
-
protein_nodes_with_embeddings.csv ~400 KB
|
| 298 |
-
drug_effects.csv ~800 KB
|
| 299 |
-
drugs_interactions.csv ~1.5 MB
|
| 300 |
-
graph_embeddings.npy ~5 MB
|
| 301 |
-
node_to_idx.npy ~50 KB
|
| 302 |
-
top_50_predicted_*.csv ~10 KB each
|
| 303 |
-
```
|
| 304 |
-
|
| 305 |
-
**Total app files**: ~10 MB
|
| 306 |
-
**With ChEMBL database**: ~4.2 GB
|
| 307 |
-
|
| 308 |
-
---
|
| 309 |
-
|
| 310 |
-
## 🤝 Contributing
|
| 311 |
-
|
| 312 |
-
If you want to improve the project:
|
| 313 |
-
|
| 314 |
-
1. Fork the repository
|
| 315 |
-
2. Run the full notebook to understand the pipeline
|
| 316 |
-
3. Make changes (better predictions, UI improvements, etc.)
|
| 317 |
-
4. Test with `python test_app.py`
|
| 318 |
-
5. Submit a pull request
|
| 319 |
-
|
| 320 |
-
---
|
| 321 |
-
|
| 322 |
-
## 📚 Additional Resources
|
| 323 |
-
|
| 324 |
-
- **ChEMBL Database**: https://www.ebi.ac.uk/chembl/
|
| 325 |
-
- **ESM-2 Model**: https://github.com/facebookresearch/esm
|
| 326 |
-
- **TransE Paper**: "Translating Embeddings for Modeling Multi-relational Data" (Bordes et al., 2013)
|
| 327 |
-
- **Gradio Docs**: https://gradio.app/docs/
|
| 328 |
-
|
| 329 |
-
---
|
| 330 |
-
|
| 331 |
-
## ⚖️ License
|
| 332 |
-
|
| 333 |
-
This project uses publicly available ChEMBL data (CC BY-SA 3.0).
|
| 334 |
-
Model and code are provided as-is for research purposes only.
|
| 335 |
-
|
| 336 |
-
**Not for clinical use.**
|
| 337 |
-
|
| 338 |
-
---
|
| 339 |
-
|
| 340 |
-
## 📧 Support
|
| 341 |
-
|
| 342 |
-
Issues? Questions?
|
| 343 |
-
- Open an issue: https://github.com/JoeVonDahab/pharmacology-graph/issues
|
| 344 |
-
- Check existing documentation: README.md, APP_GUIDE.md, DEPLOYMENT.md
|
| 345 |
-
|
| 346 |
-
---
|
| 347 |
-
|
| 348 |
-
**Last Updated**: October 10, 2025
|
| 349 |
-
**Version**: 1.0.0
|
| 350 |
-
**Python**: 3.9+
|
| 351 |
-
**Gradio**: 4.44.1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SPACE_README.md
DELETED
|
@@ -1,157 +0,0 @@
|
|
| 1 |
-
---
|
| 2 |
-
title: Pharmacology Knowledge Graph Explorer
|
| 3 |
-
emoji: 💊
|
| 4 |
-
colorFrom: blue
|
| 5 |
-
colorTo: green
|
| 6 |
-
sdk: gradio
|
| 7 |
-
sdk_version: 4.44.0
|
| 8 |
-
app_file: app.py
|
| 9 |
-
pinned: false
|
| 10 |
-
license: mit
|
| 11 |
-
---
|
| 12 |
-
|
| 13 |
-
# 💊 Pharmacology Knowledge Graph Explorer
|
| 14 |
-
|
| 15 |
-
**Explore drug-target-effect relationships using AI-powered predictions**
|
| 16 |
-
|
| 17 |
-
## 🎯 What is this?
|
| 18 |
-
|
| 19 |
-
An interactive web app that lets you explore:
|
| 20 |
-
- **Known interactions** between drugs and protein targets
|
| 21 |
-
- **Predicted novel targets** for drug repurposing
|
| 22 |
-
- **Clinical effects** and therapeutic indications
|
| 23 |
-
- **Interactive network visualizations** of drug mechanisms
|
| 24 |
-
|
| 25 |
-
## 🧬 How It Works
|
| 26 |
-
|
| 27 |
-
This app uses a **TransE knowledge graph embedding model** trained on:
|
| 28 |
-
- **800+ FDA-approved drugs** from ChEMBL database
|
| 29 |
-
- **200+ human protein targets** with ESM-2 sequence embeddings
|
| 30 |
-
- **400+ clinical effects** and disease indications
|
| 31 |
-
|
| 32 |
-
The model learns a unified embedding space where:
|
| 33 |
-
- Drugs with similar mechanisms cluster together
|
| 34 |
-
- Predictions are based on cosine similarity in latent space
|
| 35 |
-
- Novel drug-target pairs are ranked by confidence
|
| 36 |
-
|
| 37 |
-
## 🔍 Example Queries
|
| 38 |
-
|
| 39 |
-
Try searching for these drugs to see interesting results:
|
| 40 |
-
|
| 41 |
-
| Drug | What you'll see |
|
| 42 |
-
|------|----------------|
|
| 43 |
-
| **Morphine** | Opioid receptor targets, analgesic effects, similar opioids (Fentanyl, Oxycodone) |
|
| 44 |
-
| **Aspirin** | COX enzyme inhibition, anti-inflammatory effects, cardiovascular prevention |
|
| 45 |
-
| **Metformin** | Diabetes targets, metabolic effects, potential repurposing for cancer/aging |
|
| 46 |
-
| **Ibuprofen** | COX-1/COX-2 targets, NSAID effects, similar drugs (Naproxen, Diclofenac) |
|
| 47 |
-
| **Talazoparib** | PARP family targets, cancer indications, predicted PARP homologs |
|
| 48 |
-
|
| 49 |
-
## 📊 Model Performance
|
| 50 |
-
|
| 51 |
-
**Validation metrics:**
|
| 52 |
-
- **Precision@50:** ~90% pharmacologically coherent predictions
|
| 53 |
-
- **Mean similarity (top predictions):** 0.48-0.60
|
| 54 |
-
- **Baseline (random):** 0.23
|
| 55 |
-
|
| 56 |
-
**Key achievements:**
|
| 57 |
-
- ✅ Correctly clusters drugs by therapeutic class (e.g., opioids, antivirals, statins)
|
| 58 |
-
- ✅ Recovers known drug-target relationships with high accuracy
|
| 59 |
-
- ✅ Predicts plausible novel targets for experimental validation
|
| 60 |
-
|
| 61 |
-
## 🕸️ Network Visualization Features
|
| 62 |
-
|
| 63 |
-
The interactive graph shows:
|
| 64 |
-
- 🔴 **Central drug node** (red)
|
| 65 |
-
- 🔵 **Known protein targets** (blue, solid edges)
|
| 66 |
-
- 🟢 **Predicted novel targets** (green, dashed edges)
|
| 67 |
-
- 🟡 **Known clinical effects** (yellow, solid edges)
|
| 68 |
-
- 🟨 **Predicted effects** (light yellow, dashed edges)
|
| 69 |
-
|
| 70 |
-
**Controls:**
|
| 71 |
-
- Toggle known/predicted interactions
|
| 72 |
-
- Adjust max nodes displayed
|
| 73 |
-
- Hover over nodes for details
|
| 74 |
-
|
| 75 |
-
## 🚀 Use Cases
|
| 76 |
-
|
| 77 |
-
1. **Drug Repurposing:** Find new therapeutic uses for existing drugs
|
| 78 |
-
2. **Target Discovery:** Identify potential protein targets for lead compounds
|
| 79 |
-
3. **Safety Assessment:** Predict off-target effects and side effects
|
| 80 |
-
4. **Mechanism Exploration:** Understand drug action through network context
|
| 81 |
-
|
| 82 |
-
## 📖 Citation
|
| 83 |
-
|
| 84 |
-
If you use this tool in your research, please cite:
|
| 85 |
-
|
| 86 |
-
```bibtex
|
| 87 |
-
@software{pharmacology_graph_2025,
|
| 88 |
-
author = {Joe VonDahab},
|
| 89 |
-
title = {Pharmacology Knowledge Graph: Drug-Target-Effect Prediction},
|
| 90 |
-
year = {2025},
|
| 91 |
-
url = {https://github.com/JoeVonDahab/pharmacology-graph},
|
| 92 |
-
note = {Hugging Face Space: https://huggingface.co/spaces/YOUR_USERNAME/pharmacology-knowledge-graph}
|
| 93 |
-
}
|
| 94 |
-
```
|
| 95 |
-
|
| 96 |
-
## 🔗 Links
|
| 97 |
-
|
| 98 |
-
- **GitHub Repository:** [pharmacology-graph](https://github.com/JoeVonDahab/pharmacology-graph)
|
| 99 |
-
- **Paper/Blog:** *(Coming soon)*
|
| 100 |
-
- **Dataset:** [ChEMBL 36](https://www.ebi.ac.uk/chembl/)
|
| 101 |
-
- **Protein Model:** [ESM-2 (Meta AI)](https://github.com/facebookresearch/esm)
|
| 102 |
-
|
| 103 |
-
## ⚠️ Disclaimer
|
| 104 |
-
|
| 105 |
-
**This is a research tool for exploratory analysis only.**
|
| 106 |
-
|
| 107 |
-
- Predictions are computational and require experimental validation
|
| 108 |
-
- Not intended for clinical decision-making or medical diagnosis
|
| 109 |
-
- Drug repurposing candidates need rigorous testing before clinical use
|
| 110 |
-
- Always consult scientific literature and regulatory databases
|
| 111 |
-
|
| 112 |
-
## 🛠️ Technical Details
|
| 113 |
-
|
| 114 |
-
**Model Architecture:**
|
| 115 |
-
- **Graph embedding:** TransE (Translation-based)
|
| 116 |
-
- **Embedding dimension:** 128
|
| 117 |
-
- **Protein featurization:** ESM-2 (2560-dim) → mean pooling
|
| 118 |
-
- **Drug featurization:** Morgan fingerprints (2048-bit)
|
| 119 |
-
|
| 120 |
-
**Training:**
|
| 121 |
-
- Epochs: 100
|
| 122 |
-
- Learning rate: 0.01
|
| 123 |
-
- Negative sampling: 1:1 ratio
|
| 124 |
-
- Margin loss: 1.0
|
| 125 |
-
|
| 126 |
-
**Data sources:**
|
| 127 |
-
- ChEMBL 36 (drugs, targets, indications)
|
| 128 |
-
- UniProt (protein sequences)
|
| 129 |
-
- MeSH (clinical effects taxonomy)
|
| 130 |
-
|
| 131 |
-
## 💡 Future Enhancements
|
| 132 |
-
|
| 133 |
-
Planned features:
|
| 134 |
-
- [ ] SMILES input for novel molecules
|
| 135 |
-
- [ ] 3D protein structure integration (AlphaFold2)
|
| 136 |
-
- [ ] Multi-task learning (toxicity + efficacy)
|
| 137 |
-
- [ ] Batch analysis and export
|
| 138 |
-
- [ ] API endpoint for programmatic access
|
| 139 |
-
|
| 140 |
-
## 🤝 Contributing
|
| 141 |
-
|
| 142 |
-
Found a bug or have a feature request?
|
| 143 |
-
- Open an issue on [GitHub](https://github.com/JoeVonDahab/pharmacology-graph/issues)
|
| 144 |
-
- Submit a pull request
|
| 145 |
-
- Contact: [create an issue](https://github.com/JoeVonDahab/pharmacology-graph/issues)
|
| 146 |
-
|
| 147 |
-
## 📜 License
|
| 148 |
-
|
| 149 |
-
MIT License - See [LICENSE](https://github.com/JoeVonDahab/pharmacology-graph/blob/main/LICENSE) for details
|
| 150 |
-
|
| 151 |
-
---
|
| 152 |
-
|
| 153 |
-
**Built with:** 🤗 Gradio • PyTorch • NetworkX • Plotly • ESM-2
|
| 154 |
-
|
| 155 |
-
**Powered by:** ChEMBL • Hugging Face Spaces
|
| 156 |
-
|
| 157 |
-
*Last updated: October 2025*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
USER_SETUP_SUMMARY.md
DELETED
|
@@ -1,302 +0,0 @@
|
|
| 1 |
-
# 📋 Summary: Setup for New Users
|
| 2 |
-
|
| 3 |
-
## What Someone Needs to Do to Run Your App
|
| 4 |
-
|
| 5 |
-
### **Method 1: Just Run the App (Recommended for Most Users)**
|
| 6 |
-
|
| 7 |
-
```bash
|
| 8 |
-
# 1. Clone repository
|
| 9 |
-
git clone https://github.com/JoeVonDahab/pharmacology-graph.git
|
| 10 |
-
cd pharmacology-graph
|
| 11 |
-
|
| 12 |
-
# 2. Install dependencies
|
| 13 |
-
pip install -r requirements_app.txt
|
| 14 |
-
|
| 15 |
-
# 3. Download the .npy files (NOT in git)
|
| 16 |
-
# They need to either:
|
| 17 |
-
# a) Run the notebook to generate them, OR
|
| 18 |
-
# b) Download from a release/separate link you provide
|
| 19 |
-
|
| 20 |
-
# 4. Run the app
|
| 21 |
-
./start_app.sh
|
| 22 |
-
# Open browser to http://localhost:7860
|
| 23 |
-
```
|
| 24 |
-
|
| 25 |
-
**Requirements:**
|
| 26 |
-
- Python 3.9+
|
| 27 |
-
- 8GB RAM
|
| 28 |
-
- ~10MB disk space
|
| 29 |
-
|
| 30 |
-
**What they get:**
|
| 31 |
-
- ✅ Interactive web app
|
| 32 |
-
- ✅ Search 3,127 drugs
|
| 33 |
-
- ✅ View predictions
|
| 34 |
-
- ✅ Network visualization
|
| 35 |
-
|
| 36 |
-
---
|
| 37 |
-
|
| 38 |
-
### **Method 2: Full Research Pipeline (Advanced Users)**
|
| 39 |
-
|
| 40 |
-
```bash
|
| 41 |
-
# 1-2. Same as above
|
| 42 |
-
|
| 43 |
-
# 3. Download ChEMBL database (4.2GB)
|
| 44 |
-
# Already included in repo if you pushed it, otherwise:
|
| 45 |
-
# wget https://ftp.ebi.ac.uk/pub/databases/chembl/ChEMBLdb/releases/chembl_36/chembl_36_sqlite.tar.gz
|
| 46 |
-
|
| 47 |
-
# 4. Install full dependencies
|
| 48 |
-
pip install -r requirements.txt
|
| 49 |
-
|
| 50 |
-
# 5. Run the notebook
|
| 51 |
-
jupyter notebook code.ipynb
|
| 52 |
-
# Run all cells (~40 minutes)
|
| 53 |
-
|
| 54 |
-
# 6. Run the app
|
| 55 |
-
./start_app.sh
|
| 56 |
-
```
|
| 57 |
-
|
| 58 |
-
**Requirements:**
|
| 59 |
-
- Python 3.9+
|
| 60 |
-
- 16GB RAM (for ESM-2)
|
| 61 |
-
- GPU recommended (or 30+ min on CPU)
|
| 62 |
-
- ~5GB disk space
|
| 63 |
-
|
| 64 |
-
**What they get:**
|
| 65 |
-
- ✅ Everything from Method 1
|
| 66 |
-
- ✅ Ability to retrain model
|
| 67 |
-
- ✅ Explore data processing
|
| 68 |
-
- ✅ Modify predictions
|
| 69 |
-
|
| 70 |
-
---
|
| 71 |
-
|
| 72 |
-
## 🗑️ Files You Can Remove Before Sharing
|
| 73 |
-
|
| 74 |
-
Run this to clean up unnecessary files:
|
| 75 |
-
|
| 76 |
-
```bash
|
| 77 |
-
./cleanup.sh
|
| 78 |
-
```
|
| 79 |
-
|
| 80 |
-
Or manually remove:
|
| 81 |
-
|
| 82 |
-
### Definitely Remove (Duplicates/Debugging)
|
| 83 |
-
```bash
|
| 84 |
-
rm -f BUGFIX_SUMMARY.md # Development notes
|
| 85 |
-
rm -f APP_SUMMARY.md # Duplicate of APP_GUIDE.md
|
| 86 |
-
rm -f CHECKLIST.md # One-time deployment checklist
|
| 87 |
-
rm -f run_app.sh # Old script (use start_app.sh)
|
| 88 |
-
rm -f test_search.py # Manual testing guide
|
| 89 |
-
rm -f main.py # Old experimental code
|
| 90 |
-
rm -f .python-version # Unnecessary version pin
|
| 91 |
-
```
|
| 92 |
-
|
| 93 |
-
### Optional Remove (Can Regenerate)
|
| 94 |
-
```bash
|
| 95 |
-
rm -f *.png # Visualization outputs
|
| 96 |
-
rm -f *.pkl # Pickle files
|
| 97 |
-
rm -f drug_mechanism_filtered.csv
|
| 98 |
-
rm -f drug_warnings.csv
|
| 99 |
-
rm -f edges_drug_protein.csv
|
| 100 |
-
rm -f proteins_for_embedding.csv
|
| 101 |
-
rm -f top_50_predicted_drug_targets.csv # Duplicate
|
| 102 |
-
```
|
| 103 |
-
|
| 104 |
-
### Consider Removing (If Users Don't Need to Retrain)
|
| 105 |
-
```bash
|
| 106 |
-
rm -f code.ipynb # Research notebook (750KB)
|
| 107 |
-
rm -f requirements.txt # Full deps (use requirements_app.txt only)
|
| 108 |
-
rm -rf chembl_36/ # Database (4.2GB!)
|
| 109 |
-
```
|
| 110 |
-
|
| 111 |
-
---
|
| 112 |
-
|
| 113 |
-
## 📦 Minimal File Set for App-Only Distribution
|
| 114 |
-
|
| 115 |
-
After cleanup, you'd have:
|
| 116 |
-
|
| 117 |
-
```
|
| 118 |
-
pharmacology-graph/
|
| 119 |
-
├── app.py # Main app
|
| 120 |
-
├── requirements_app.txt # Dependencies
|
| 121 |
-
├── start_app.sh # Launcher
|
| 122 |
-
├── test_app.py # Diagnostic
|
| 123 |
-
├── README.md # Overview
|
| 124 |
-
├── SETUP.md # Setup guide ⭐
|
| 125 |
-
├── FILES.md # This file list
|
| 126 |
-
├── DEPLOYMENT.md # HF Spaces guide
|
| 127 |
-
├── APP_GUIDE.md # User guide
|
| 128 |
-
├── SPACE_README.md # For HF deployment
|
| 129 |
-
├── drug_nodes.csv # Data
|
| 130 |
-
├── protein_nodes_with_embeddings.csv # Data
|
| 131 |
-
├── drug_effects.csv # Data
|
| 132 |
-
├── drugs_interactions.csv # Data
|
| 133 |
-
├── top_50_predicted_drug_protein.csv # Predictions
|
| 134 |
-
├── top_50_predicted_drug_effects.csv # Predictions
|
| 135 |
-
├── graph_embeddings.npy # Model ⚠️ NOT IN GIT
|
| 136 |
-
├── node_to_idx.npy # Mapping ⚠️ NOT IN GIT
|
| 137 |
-
└── .gitignore # Git config
|
| 138 |
-
```
|
| 139 |
-
|
| 140 |
-
**Total size**: ~10 MB (without .npy files)
|
| 141 |
-
|
| 142 |
-
---
|
| 143 |
-
|
| 144 |
-
## ⚠️ IMPORTANT: The .npy Files Problem
|
| 145 |
-
|
| 146 |
-
### The Issue
|
| 147 |
-
The `.npy` files (`graph_embeddings.npy` and `node_to_idx.npy`) are:
|
| 148 |
-
- **Essential** for the app to run
|
| 149 |
-
- **NOT tracked in git** (they're in `.gitignore`)
|
| 150 |
-
- **~5MB total** (not huge, but binary)
|
| 151 |
-
|
| 152 |
-
### Solutions
|
| 153 |
-
|
| 154 |
-
**Option 1: Add them to git** (Simplest)
|
| 155 |
-
```bash
|
| 156 |
-
# Edit .gitignore to allow these specific files
|
| 157 |
-
echo '!graph_embeddings.npy' >> .gitignore
|
| 158 |
-
echo '!node_to_idx.npy' >> .gitignore
|
| 159 |
-
|
| 160 |
-
# Add and push
|
| 161 |
-
git add graph_embeddings.npy node_to_idx.npy
|
| 162 |
-
git commit -m "Add model embeddings"
|
| 163 |
-
git push
|
| 164 |
-
```
|
| 165 |
-
|
| 166 |
-
**Option 2: GitHub Release** (Cleaner)
|
| 167 |
-
1. Go to GitHub → Releases → Create new release
|
| 168 |
-
2. Upload `graph_embeddings.npy` and `node_to_idx.npy`
|
| 169 |
-
3. Update SETUP.md with download instructions:
|
| 170 |
-
```bash
|
| 171 |
-
# Download embeddings
|
| 172 |
-
wget https://github.com/YOUR_USERNAME/pharmacology-graph/releases/download/v1.0/graph_embeddings.npy
|
| 173 |
-
wget https://github.com/YOUR_USERNAME/pharmacology-graph/releases/download/v1.0/node_to_idx.npy
|
| 174 |
-
```
|
| 175 |
-
|
| 176 |
-
**Option 3: Git LFS** (Professional)
|
| 177 |
-
```bash
|
| 178 |
-
# Install Git LFS
|
| 179 |
-
git lfs install
|
| 180 |
-
|
| 181 |
-
# Track .npy files
|
| 182 |
-
git lfs track "*.npy"
|
| 183 |
-
git add .gitattributes
|
| 184 |
-
|
| 185 |
-
# Add and push
|
| 186 |
-
git add graph_embeddings.npy node_to_idx.npy
|
| 187 |
-
git commit -m "Add model embeddings via LFS"
|
| 188 |
-
git push
|
| 189 |
-
```
|
| 190 |
-
|
| 191 |
-
**Option 4: External Storage** (If files are huge)
|
| 192 |
-
- Upload to Hugging Face Hub, Google Drive, Dropbox
|
| 193 |
-
- Provide download link in SETUP.md
|
| 194 |
-
|
| 195 |
-
### Recommendation
|
| 196 |
-
For 5MB files, **Option 1** (just add to git) is fine. GitHub allows files up to 100MB.
|
| 197 |
-
|
| 198 |
-
---
|
| 199 |
-
|
| 200 |
-
## 📝 Updated SETUP.md Instructions
|
| 201 |
-
|
| 202 |
-
I've created **`SETUP.md`** with complete instructions including:
|
| 203 |
-
|
| 204 |
-
✅ **Quick Start** (3 commands)
|
| 205 |
-
✅ **Full Setup** (retrain from scratch)
|
| 206 |
-
✅ **Troubleshooting** (version issues, port conflicts)
|
| 207 |
-
✅ **Testing** (verify it works)
|
| 208 |
-
✅ **Deployment** (Hugging Face Spaces)
|
| 209 |
-
✅ **File cleanup** (remove unnecessary files)
|
| 210 |
-
|
| 211 |
-
**For new users, tell them:**
|
| 212 |
-
> "Read **SETUP.md** for complete installation and usage instructions."
|
| 213 |
-
|
| 214 |
-
---
|
| 215 |
-
|
| 216 |
-
## 🎯 Recommended Git Workflow
|
| 217 |
-
|
| 218 |
-
### Before sharing on GitHub:
|
| 219 |
-
|
| 220 |
-
1. **Clean up files**:
|
| 221 |
-
```bash
|
| 222 |
-
./cleanup.sh
|
| 223 |
-
```
|
| 224 |
-
|
| 225 |
-
2. **Add .npy files to git** (if you choose Option 1):
|
| 226 |
-
```bash
|
| 227 |
-
echo '!graph_embeddings.npy' >> .gitignore
|
| 228 |
-
echo '!node_to_idx.npy' >> .gitignore
|
| 229 |
-
git add graph_embeddings.npy node_to_idx.npy .gitignore
|
| 230 |
-
git commit -m "Add model embeddings for app"
|
| 231 |
-
```
|
| 232 |
-
|
| 233 |
-
3. **Update README**:
|
| 234 |
-
- Already updated with Quick Start section
|
| 235 |
-
- Points to SETUP.md for details
|
| 236 |
-
|
| 237 |
-
4. **Push everything**:
|
| 238 |
-
```bash
|
| 239 |
-
git add .
|
| 240 |
-
git commit -m "Add setup documentation and cleanup scripts"
|
| 241 |
-
git push
|
| 242 |
-
```
|
| 243 |
-
|
| 244 |
-
### User experience:
|
| 245 |
-
```bash
|
| 246 |
-
git clone https://github.com/YOUR_USERNAME/pharmacology-graph
|
| 247 |
-
cd pharmacology-graph
|
| 248 |
-
pip install -r requirements_app.txt
|
| 249 |
-
./start_app.sh
|
| 250 |
-
```
|
| 251 |
-
|
| 252 |
-
**That's it!** 3 commands and they're running.
|
| 253 |
-
|
| 254 |
-
---
|
| 255 |
-
|
| 256 |
-
## 📊 File Organization Summary
|
| 257 |
-
|
| 258 |
-
| Category | Files | Purpose | Size | In Git? |
|
| 259 |
-
|----------|-------|---------|------|---------|
|
| 260 |
-
| **App Core** | app.py, start_app.sh | Run the interface | 50KB | ✅ Yes |
|
| 261 |
-
| **Data** | 6 CSV files | Drug/protein/effect data | 3.5MB | ✅ Yes |
|
| 262 |
-
| **Model** | 2 NPY files | Trained embeddings | 5MB | ⚠️ **No** (need to add) |
|
| 263 |
-
| **Predictions** | 2 CSV files | Top 50 predictions | 20KB | ✅ Yes |
|
| 264 |
-
| **Docs** | 7 MD files | Setup, deployment, usage | 50KB | ✅ Yes |
|
| 265 |
-
| **Research** | code.ipynb | Full pipeline | 500KB | ✅ Yes |
|
| 266 |
-
| **Database** | chembl_36/ | ChEMBL SQLite | 4.2GB | ❌ No (too large) |
|
| 267 |
-
| **Cleanup** | 10+ files | Duplicates, old versions | 2MB | ✅ Yes (but can remove) |
|
| 268 |
-
|
| 269 |
-
**Action Items:**
|
| 270 |
-
1. ✅ Created SETUP.md (complete guide)
|
| 271 |
-
2. ✅ Created FILES.md (file manifest)
|
| 272 |
-
3. ✅ Created cleanup.sh (remove junk)
|
| 273 |
-
4. ✅ Updated README.md (quick start)
|
| 274 |
-
5. ⚠️ **TODO**: Decide how to distribute .npy files (Option 1-4 above)
|
| 275 |
-
|
| 276 |
-
---
|
| 277 |
-
|
| 278 |
-
## 🎓 Bottom Line
|
| 279 |
-
|
| 280 |
-
**For someone to download and run your app, they need:**
|
| 281 |
-
|
| 282 |
-
### Minimum (App Only):
|
| 283 |
-
1. Clone repo
|
| 284 |
-
2. `pip install -r requirements_app.txt`
|
| 285 |
-
3. Download/generate `.npy` files
|
| 286 |
-
4. `./start_app.sh`
|
| 287 |
-
|
| 288 |
-
### Full (Research):
|
| 289 |
-
1. Clone repo
|
| 290 |
-
2. `pip install -r requirements.txt`
|
| 291 |
-
3. Download ChEMBL (or use included)
|
| 292 |
-
4. Run notebook → generates everything
|
| 293 |
-
5. `./start_app.sh`
|
| 294 |
-
|
| 295 |
-
**Unnecessary files removed**: ~15 files, saving 2MB and reducing clutter
|
| 296 |
-
|
| 297 |
-
**New documentation**:
|
| 298 |
-
- ✅ SETUP.md (start here!)
|
| 299 |
-
- ✅ FILES.md (what each file does)
|
| 300 |
-
- ✅ cleanup.sh (automated cleanup)
|
| 301 |
-
|
| 302 |
-
Users should read **SETUP.md** first. It has everything they need.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app.js
ADDED
|
@@ -0,0 +1,233 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
'use strict';
|
| 2 |
+
|
| 3 |
+
const V = 'p5'; // bump on each data/app redeploy to bust caches
|
| 4 |
+
// ponytail: data is served by the project's GitHub Pages (CORS: access-control-allow-origin *),
|
| 5 |
+
// so this static Space stays ~25KB and shares one source of truth. Point at local 'data' if self-hosting.
|
| 6 |
+
const DATA = 'https://joevondahab.github.io/pharmacology-graph/data';
|
| 7 |
+
const bust = u => `${u}${u.includes('?') ? '&' : '?'}v=${V}`;
|
| 8 |
+
const CHEMBL_CMP = id => `https://www.ebi.ac.uk/chembl/explore/compound/${id}`;
|
| 9 |
+
const CHEMBL_TGT = id => `https://www.ebi.ac.uk/chembl/explore/target/${id}`;
|
| 10 |
+
const MESH = id => `https://meshb.nlm.nih.gov/record/ui?ui=${id}`;
|
| 11 |
+
const EXT = { drug: CHEMBL_CMP, protein: CHEMBL_TGT, mesh: MESH };
|
| 12 |
+
|
| 13 |
+
// entity-type config for search + display
|
| 14 |
+
const TYPES = {
|
| 15 |
+
drug: { label: 'Drug', chip: 'drug', file: id => `predictions/${id}.json`, index: 'drugs.json' },
|
| 16 |
+
indication: { label: 'Indication', chip: 'ind', file: id => `by_indication/${id}.json`, index: 'indications.json' },
|
| 17 |
+
protein: { label: 'Protein', chip: 'prot', file: id => `by_protein/${id}.json`, index: 'proteins.json' },
|
| 18 |
+
};
|
| 19 |
+
|
| 20 |
+
let ENTITIES = []; // combined search index: {type,id,name,...counts}
|
| 21 |
+
let current = null; // {type, view:[{key,label,linkType}], data}
|
| 22 |
+
let activeList = null;
|
| 23 |
+
let statusFilter = 'all';
|
| 24 |
+
|
| 25 |
+
const $ = s => document.querySelector(s);
|
| 26 |
+
const esc = s => String(s).replace(/[&<>"']/g, c => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]));
|
| 27 |
+
|
| 28 |
+
async function init() {
|
| 29 |
+
try {
|
| 30 |
+
const [drugs, inds, prots, meta] = await Promise.all([
|
| 31 |
+
fetch(bust(`${DATA}/drugs.json`)).then(r => r.json()),
|
| 32 |
+
fetch(bust(`${DATA}/indications.json`)).then(r => r.json()),
|
| 33 |
+
fetch(bust(`${DATA}/proteins.json`)).then(r => r.json()),
|
| 34 |
+
fetch(bust(`${DATA}/meta.json`)).then(r => r.json()).catch(() => null),
|
| 35 |
+
]);
|
| 36 |
+
ENTITIES = [
|
| 37 |
+
...drugs.map(d => ({ ...d, type: 'drug' })),
|
| 38 |
+
...inds.map(d => ({ ...d, type: 'indication' })),
|
| 39 |
+
...prots.map(d => ({ ...d, type: 'protein' })),
|
| 40 |
+
];
|
| 41 |
+
if (meta) {
|
| 42 |
+
$('#meta-line').textContent =
|
| 43 |
+
`${meta.num_drugs.toLocaleString()} drugs · ${meta.num_proteins.toLocaleString()} proteins · ` +
|
| 44 |
+
`${meta.num_indications.toLocaleString()} indications · top-${meta.top_k} each way`;
|
| 45 |
+
if (meta.metrics) {
|
| 46 |
+
const m = meta.metrics;
|
| 47 |
+
$('#metrics-note').textContent =
|
| 48 |
+
`Model test metrics — Drug–Protein PR-AUC ${m.dp.pr_auc.toFixed(3)}, Hits@10 ${m.dp['hits@10'].toFixed(3)} · ` +
|
| 49 |
+
`Drug–Indication PR-AUC ${m.di.pr_auc.toFixed(3)}, Hits@10 ${m.di['hits@10'].toFixed(3)}`;
|
| 50 |
+
}
|
| 51 |
+
}
|
| 52 |
+
buildExamples();
|
| 53 |
+
wireSearch();
|
| 54 |
+
if (location.hash.length > 1) {
|
| 55 |
+
const [t, id] = decodeURIComponent(location.hash.slice(1)).split(':');
|
| 56 |
+
if (id) select(t, id);
|
| 57 |
+
}
|
| 58 |
+
} catch (e) {
|
| 59 |
+
$('#empty-state').innerHTML = `<p style="color:#e06b6b">Failed to load data (${e}). Serve this folder over HTTP.</p>`;
|
| 60 |
+
}
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
function buildExamples() {
|
| 64 |
+
const picks = [
|
| 65 |
+
['drug', 'SUNITINIB'], ['indication', 'Breast Neoplasms'],
|
| 66 |
+
['drug', 'ASPIRIN'], ['indication', 'Hypertension'], ['protein', 'Histamine H1 receptor'],
|
| 67 |
+
];
|
| 68 |
+
const box = $('#examples');
|
| 69 |
+
picks.forEach(([type, name]) => {
|
| 70 |
+
const e = ENTITIES.find(x => x.type === type && x.name.toUpperCase() === name.toUpperCase());
|
| 71 |
+
if (!e) return;
|
| 72 |
+
const b = document.createElement('button');
|
| 73 |
+
b.innerHTML = `<span class="chip ${TYPES[type].chip}">${TYPES[type].label}</span> ${esc(e.name)}`;
|
| 74 |
+
b.onclick = () => select(type, e.id);
|
| 75 |
+
box.appendChild(b);
|
| 76 |
+
});
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
// ---------- search ----------
|
| 80 |
+
let activeIdx = -1, matches = [];
|
| 81 |
+
function wireSearch() {
|
| 82 |
+
const input = $('#search'), list = $('#suggestions');
|
| 83 |
+
input.addEventListener('input', () => {
|
| 84 |
+
const q = input.value.trim().toLowerCase();
|
| 85 |
+
if (!q) { list.hidden = true; return; }
|
| 86 |
+
matches = ENTITIES
|
| 87 |
+
.filter(e => e.name.toLowerCase().includes(q) || e.id.toLowerCase().includes(q))
|
| 88 |
+
.sort((a, b) => (a.name.toLowerCase().indexOf(q) - b.name.toLowerCase().indexOf(q)) || a.name.length - b.name.length)
|
| 89 |
+
.slice(0, 14);
|
| 90 |
+
renderSuggestions(q);
|
| 91 |
+
});
|
| 92 |
+
input.addEventListener('keydown', e => {
|
| 93 |
+
if (list.hidden) return;
|
| 94 |
+
if (e.key === 'ArrowDown') { activeIdx = Math.min(activeIdx + 1, matches.length - 1); paint(); e.preventDefault(); }
|
| 95 |
+
else if (e.key === 'ArrowUp') { activeIdx = Math.max(activeIdx - 1, 0); paint(); e.preventDefault(); }
|
| 96 |
+
else if (e.key === 'Enter') { const m = matches[activeIdx] || matches[0]; if (m) select(m.type, m.id); }
|
| 97 |
+
else if (e.key === 'Escape') list.hidden = true;
|
| 98 |
+
});
|
| 99 |
+
document.addEventListener('click', e => { if (!e.target.closest('.search-box')) list.hidden = true; });
|
| 100 |
+
}
|
| 101 |
+
function renderSuggestions(q) {
|
| 102 |
+
const list = $('#suggestions'); activeIdx = -1;
|
| 103 |
+
if (!matches.length) { list.hidden = true; return; }
|
| 104 |
+
list.innerHTML = matches.map((e, i) => {
|
| 105 |
+
const t = TYPES[e.type];
|
| 106 |
+
const sub = e.type === 'drug' ? `${e.kp}+${e.ki} known` : `${e.kd} known drugs`;
|
| 107 |
+
return `<li data-i="${i}"><span class="s-left"><span class="chip ${t.chip}">${t.label}</span>
|
| 108 |
+
<span class="sname">${hl(e.name, q)}</span></span><span class="sid">${e.id} · ${sub}</span></li>`;
|
| 109 |
+
}).join('');
|
| 110 |
+
[...list.children].forEach((li, i) => li.onclick = () => select(matches[i].type, matches[i].id));
|
| 111 |
+
list.hidden = false;
|
| 112 |
+
}
|
| 113 |
+
function paint() { [...$('#suggestions').children].forEach(li => li.classList.toggle('active', +li.dataset.i === activeIdx)); }
|
| 114 |
+
function hl(text, q) {
|
| 115 |
+
const i = text.toLowerCase().indexOf(q);
|
| 116 |
+
return i < 0 ? esc(text) : esc(text.slice(0, i)) + '<mark>' + esc(text.slice(i, i + q.length)) + '</mark>' + esc(text.slice(i + q.length));
|
| 117 |
+
}
|
| 118 |
+
|
| 119 |
+
// ---------- selection ----------
|
| 120 |
+
async function select(type, id) {
|
| 121 |
+
$('#suggestions').hidden = true; $('#search').value = '';
|
| 122 |
+
let data;
|
| 123 |
+
try {
|
| 124 |
+
data = await fetch(bust(`${DATA}/${TYPES[type].file(id)}`)).then(r => { if (!r.ok) throw new Error(r.status); return r.json(); });
|
| 125 |
+
} catch (e) { alert(`No predictions found for ${type} "${id}".`); return; }
|
| 126 |
+
|
| 127 |
+
let view, head;
|
| 128 |
+
if (type === 'drug') {
|
| 129 |
+
view = [{ key: 'proteins', label: 'Protein targets', linkType: 'protein' },
|
| 130 |
+
{ key: 'indications', label: 'Indications', linkType: 'mesh' }];
|
| 131 |
+
head = { name: data.drug.name, id: data.drug.id, ext: 'drug' };
|
| 132 |
+
} else if (type === 'indication') {
|
| 133 |
+
view = [{ key: 'drugs', label: 'Predicted drugs', linkType: 'drug' }];
|
| 134 |
+
head = { name: data.indication.name, id: data.indication.id, ext: 'mesh' };
|
| 135 |
+
} else {
|
| 136 |
+
view = [{ key: 'drugs', label: 'Predicted drugs', linkType: 'drug' }];
|
| 137 |
+
head = { name: data.protein.name, id: data.protein.id, ext: 'protein' };
|
| 138 |
+
}
|
| 139 |
+
current = { type, view, data, head };
|
| 140 |
+
activeList = view[0].key; statusFilter = 'all';
|
| 141 |
+
history.replaceState(null, '', `#${type}:${id}`);
|
| 142 |
+
$('#empty-state').hidden = true; $('#result').hidden = false;
|
| 143 |
+
renderHead(); renderControls(); renderTable();
|
| 144 |
+
}
|
| 145 |
+
|
| 146 |
+
function renderHead() {
|
| 147 |
+
const { type, head, view, data } = current;
|
| 148 |
+
$('#drug-name').textContent = head.name;
|
| 149 |
+
$('#type-chip').className = `chip ${TYPES[type].chip}`;
|
| 150 |
+
$('#type-chip').textContent = TYPES[type].label;
|
| 151 |
+
const link = $('#drug-link'); link.href = EXT[head.ext](head.id); link.textContent = `${head.id} ↗`;
|
| 152 |
+
|
| 153 |
+
const cards = [];
|
| 154 |
+
const count = (key, st) => (data[key] || []).filter(r => r.status === st).length;
|
| 155 |
+
if (type === 'drug') {
|
| 156 |
+
cards.push(['known', count('proteins', 'known'), 'known prot'], ['novel', count('proteins', 'novel'), 'novel prot'],
|
| 157 |
+
['known', count('indications', 'known'), 'known ind'], ['novel', count('indications', 'novel'), 'novel ind']);
|
| 158 |
+
} else {
|
| 159 |
+
cards.push(['known', count('drugs', 'known'), 'known drugs'], ['novel', count('drugs', 'novel'), 'novel drugs']);
|
| 160 |
+
}
|
| 161 |
+
$('#stat-cards').innerHTML = cards.map(([c, n, l]) => `<div class="stat ${c}"><b>${n}</b><span>${l}</span></div>`).join('');
|
| 162 |
+
}
|
| 163 |
+
|
| 164 |
+
function renderControls() {
|
| 165 |
+
const tabs = $('#tabs');
|
| 166 |
+
if (current.view.length > 1) {
|
| 167 |
+
tabs.hidden = false;
|
| 168 |
+
tabs.innerHTML = current.view.map(v =>
|
| 169 |
+
`<button class="tab ${v.key === activeList ? 'active' : ''}" data-list="${v.key}">${v.label}</button>`).join('');
|
| 170 |
+
} else { tabs.hidden = true; }
|
| 171 |
+
}
|
| 172 |
+
|
| 173 |
+
function activeRows() {
|
| 174 |
+
const rows = current.data[activeList] || [];
|
| 175 |
+
const q = $('#table-filter').value.trim().toLowerCase();
|
| 176 |
+
return rows.filter(r => statusFilter === 'all' || r.status === statusFilter)
|
| 177 |
+
.filter(r => !q || r.name.toLowerCase().includes(q) || r.id.toLowerCase().includes(q));
|
| 178 |
+
}
|
| 179 |
+
|
| 180 |
+
function renderTable() {
|
| 181 |
+
const v = current.view.find(x => x.key === activeList);
|
| 182 |
+
const linkFn = EXT[v.linkType];
|
| 183 |
+
const colHead = v.linkType === 'drug' ? 'Drug' : (v.linkType === 'protein' ? 'Target' : 'Indication');
|
| 184 |
+
$('#th-target').textContent = colHead;
|
| 185 |
+
const rows = activeRows();
|
| 186 |
+
$('#pred-body').innerHTML = rows.map(r => `
|
| 187 |
+
<tr>
|
| 188 |
+
<td class="c-rank">${r.rank}</td>
|
| 189 |
+
<td class="tname">${esc(r.name)}</td>
|
| 190 |
+
<td class="tid"><a href="${linkFn(r.id)}" target="_blank" rel="noopener">${r.id} ↗</a></td>
|
| 191 |
+
<td><div class="scorewrap"><div class="bar"><i style="width:${Math.round(r.score * 100)}%"></i></div>
|
| 192 |
+
<span class="scoreval">${r.score.toFixed(3)}</span></div></td>
|
| 193 |
+
<td><span class="badge ${r.status}">${r.status}</span></td>
|
| 194 |
+
</tr>`).join('');
|
| 195 |
+
$('#no-rows').hidden = rows.length > 0;
|
| 196 |
+
}
|
| 197 |
+
|
| 198 |
+
// ---------- controls ----------
|
| 199 |
+
document.addEventListener('click', e => {
|
| 200 |
+
const t = e.target;
|
| 201 |
+
if (t.classList.contains('tab')) { activeList = t.dataset.list; renderControls(); renderTable(); }
|
| 202 |
+
if (t.classList.contains('chip') && t.dataset.status) {
|
| 203 |
+
statusFilter = t.dataset.status;
|
| 204 |
+
document.querySelectorAll('#status-filter .chip').forEach(x => x.classList.toggle('active', x === t));
|
| 205 |
+
renderTable();
|
| 206 |
+
}
|
| 207 |
+
if (t.id === 'dl-csv') downloadCSV();
|
| 208 |
+
if (t.id === 'dl-json') downloadJSON();
|
| 209 |
+
});
|
| 210 |
+
document.addEventListener('input', e => { if (e.target.id === 'table-filter') renderTable(); });
|
| 211 |
+
|
| 212 |
+
// ---------- downloads ----------
|
| 213 |
+
function downloadCSV() {
|
| 214 |
+
if (!current) return;
|
| 215 |
+
const v = current.view.find(x => x.key === activeList);
|
| 216 |
+
const what = v.linkType === 'drug' ? 'drug' : (v.linkType === 'protein' ? 'protein' : 'indication');
|
| 217 |
+
const head = ['rank', `${what}_id`, `${what}_name`, 'score', 'raw_score', 'status'];
|
| 218 |
+
const lines = [head.join(',')];
|
| 219 |
+
for (const r of activeRows())
|
| 220 |
+
lines.push([r.rank, r.id, `"${r.name.replace(/"/g, '""')}"`, r.score, r.raw ?? '', r.status].join(','));
|
| 221 |
+
save(lines.join('\n'), `${current.head.id}_${activeList}.csv`, 'text/csv');
|
| 222 |
+
}
|
| 223 |
+
function downloadJSON() {
|
| 224 |
+
if (!current) return;
|
| 225 |
+
save(JSON.stringify(current.data, null, 2), `${current.head.id}_predictions.json`, 'application/json');
|
| 226 |
+
}
|
| 227 |
+
function save(text, name, type) {
|
| 228 |
+
const url = URL.createObjectURL(new Blob([text], { type }));
|
| 229 |
+
const a = document.createElement('a'); a.href = url; a.download = name; a.click();
|
| 230 |
+
setTimeout(() => URL.revokeObjectURL(url), 1000);
|
| 231 |
+
}
|
| 232 |
+
|
| 233 |
+
init();
|
app.py
DELETED
|
@@ -1,609 +0,0 @@
|
|
| 1 |
-
import gradio as gr
|
| 2 |
-
import pandas as pd
|
| 3 |
-
import numpy as np
|
| 4 |
-
import plotly.graph_objects as go
|
| 5 |
-
import networkx as nx
|
| 6 |
-
from sklearn.metrics.pairwise import cosine_similarity
|
| 7 |
-
import json
|
| 8 |
-
|
| 9 |
-
# Load data
|
| 10 |
-
print("Loading data...")
|
| 11 |
-
drug_nodes = pd.read_csv('drug_nodes.csv')
|
| 12 |
-
protein_nodes = pd.read_csv('protein_nodes_with_embeddings.csv')
|
| 13 |
-
drug_effects = pd.read_csv('drug_effects.csv')
|
| 14 |
-
drugs_interactions = pd.read_csv('drugs_interactions.csv')
|
| 15 |
-
|
| 16 |
-
# Load predictions
|
| 17 |
-
predicted_targets = pd.read_csv('top_50_predicted_drug_protein.csv')
|
| 18 |
-
predicted_effects = pd.read_csv('top_50_predicted_drug_effects.csv')
|
| 19 |
-
|
| 20 |
-
# Load embeddings
|
| 21 |
-
embeddings = np.load('graph_embeddings.npy')
|
| 22 |
-
node_to_idx = np.load('node_to_idx.npy', allow_pickle=True).item()
|
| 23 |
-
|
| 24 |
-
print(f"✓ Loaded {len(drug_nodes)} drugs, {len(protein_nodes)} proteins, {len(drug_effects)} effects")
|
| 25 |
-
|
| 26 |
-
# Create reverse mappings
|
| 27 |
-
internal_to_drug_info = dict(zip(drug_nodes['drug_internal_id'],
|
| 28 |
-
zip(drug_nodes['drug_id'], drug_nodes['drug_name'])))
|
| 29 |
-
protein_id_to_name = dict(zip(protein_nodes['protein_id'], protein_nodes['protein_name']))
|
| 30 |
-
effect_id_to_name = dict(zip(drug_effects['effect_id'], drug_effects['effect_name']))
|
| 31 |
-
|
| 32 |
-
def search_drugs(query):
|
| 33 |
-
"""Search for drugs by name or ChEMBL ID"""
|
| 34 |
-
try:
|
| 35 |
-
if not query:
|
| 36 |
-
return []
|
| 37 |
-
|
| 38 |
-
query = query.lower()
|
| 39 |
-
matches = drug_nodes[
|
| 40 |
-
drug_nodes['drug_name'].str.lower().str.contains(query, na=False) |
|
| 41 |
-
drug_nodes['drug_id'].str.lower().str.contains(query, na=False)
|
| 42 |
-
]
|
| 43 |
-
|
| 44 |
-
# Return list of tuples (display_name, drug_internal_id)
|
| 45 |
-
results = [(f"{row['drug_name']} ({row['drug_id']})", row['drug_internal_id'])
|
| 46 |
-
for _, row in matches.head(20).iterrows()]
|
| 47 |
-
|
| 48 |
-
return results
|
| 49 |
-
except Exception as e:
|
| 50 |
-
print(f"Error in search_drugs: {e}")
|
| 51 |
-
return []
|
| 52 |
-
|
| 53 |
-
def get_drug_info(drug_internal_id):
|
| 54 |
-
"""Get basic drug information"""
|
| 55 |
-
if drug_internal_id is None:
|
| 56 |
-
return "No drug selected"
|
| 57 |
-
|
| 58 |
-
drug_row = drug_nodes[drug_nodes['drug_internal_id'] == drug_internal_id]
|
| 59 |
-
if len(drug_row) == 0:
|
| 60 |
-
return "Drug not found"
|
| 61 |
-
|
| 62 |
-
drug_row = drug_row.iloc[0]
|
| 63 |
-
|
| 64 |
-
info = f"""
|
| 65 |
-
## 💊 {drug_row['drug_name']}
|
| 66 |
-
|
| 67 |
-
**ChEMBL ID:** {drug_row['drug_id']}
|
| 68 |
-
**SMILES:** `{drug_row['smile'][:100]}...`
|
| 69 |
-
"""
|
| 70 |
-
return info
|
| 71 |
-
|
| 72 |
-
def get_known_targets(drug_internal_id):
|
| 73 |
-
"""Get known protein targets for a drug"""
|
| 74 |
-
if drug_internal_id is None:
|
| 75 |
-
return pd.DataFrame()
|
| 76 |
-
|
| 77 |
-
# Get ChEMBL ID
|
| 78 |
-
drug_row = drug_nodes[drug_nodes['drug_internal_id'] == drug_internal_id]
|
| 79 |
-
if len(drug_row) == 0:
|
| 80 |
-
return pd.DataFrame()
|
| 81 |
-
|
| 82 |
-
drug_chembl_id = drug_row.iloc[0]['drug_id']
|
| 83 |
-
|
| 84 |
-
# Get known interactions
|
| 85 |
-
known = drugs_interactions[drugs_interactions['drug_id'] == drug_chembl_id].copy()
|
| 86 |
-
|
| 87 |
-
if len(known) == 0:
|
| 88 |
-
return pd.DataFrame(columns=['Target Protein', 'pChEMBL (max)', 'Measurements'])
|
| 89 |
-
|
| 90 |
-
# Format for display
|
| 91 |
-
display_df = pd.DataFrame({
|
| 92 |
-
'Target Protein': known['protein_name'].values,
|
| 93 |
-
'ChEMBL ID': known['protein_id'].values,
|
| 94 |
-
'pChEMBL (max)': known['pchembl_max'].values,
|
| 95 |
-
'pChEMBL (avg)': known['pchembl_avg'].values,
|
| 96 |
-
'Measurements': known['num_measurements'].values
|
| 97 |
-
})
|
| 98 |
-
|
| 99 |
-
return display_df.sort_values('pChEMBL (max)', ascending=False)
|
| 100 |
-
|
| 101 |
-
def get_known_effects(drug_internal_id):
|
| 102 |
-
"""Get known clinical effects for a drug"""
|
| 103 |
-
if drug_internal_id is None:
|
| 104 |
-
return pd.DataFrame()
|
| 105 |
-
|
| 106 |
-
# Get known effects
|
| 107 |
-
known = drug_effects[drug_effects['drug_internal_id'] == drug_internal_id].copy()
|
| 108 |
-
|
| 109 |
-
if len(known) == 0:
|
| 110 |
-
return pd.DataFrame(columns=['Clinical Effect', 'Phase', 'References'])
|
| 111 |
-
|
| 112 |
-
# Format for display
|
| 113 |
-
display_df = pd.DataFrame({
|
| 114 |
-
'Clinical Effect': known['effect_name'].values,
|
| 115 |
-
'MeSH ID': known['effect_id'].values,
|
| 116 |
-
'Phase': known['indication_phase'].values,
|
| 117 |
-
'References': known['num_references'].values
|
| 118 |
-
})
|
| 119 |
-
|
| 120 |
-
return display_df.sort_values('Phase', ascending=False)
|
| 121 |
-
|
| 122 |
-
def get_predicted_targets(drug_internal_id, top_k=10):
|
| 123 |
-
"""Get predicted novel protein targets"""
|
| 124 |
-
if drug_internal_id is None:
|
| 125 |
-
return pd.DataFrame()
|
| 126 |
-
|
| 127 |
-
# Get ChEMBL ID
|
| 128 |
-
drug_row = drug_nodes[drug_nodes['drug_internal_id'] == drug_internal_id]
|
| 129 |
-
if len(drug_row) == 0:
|
| 130 |
-
return pd.DataFrame()
|
| 131 |
-
|
| 132 |
-
drug_chembl_id = drug_row.iloc[0]['drug_id']
|
| 133 |
-
|
| 134 |
-
# Get known targets to filter out
|
| 135 |
-
known_targets = set(drugs_interactions[
|
| 136 |
-
drugs_interactions['drug_id'] == drug_chembl_id
|
| 137 |
-
]['protein_id'].values)
|
| 138 |
-
|
| 139 |
-
# Check if drug is in embedding space
|
| 140 |
-
if drug_internal_id not in node_to_idx:
|
| 141 |
-
return pd.DataFrame(columns=['Predicted Target', 'Similarity', 'Confidence'])
|
| 142 |
-
|
| 143 |
-
# Get drug embedding
|
| 144 |
-
drug_idx = node_to_idx[drug_internal_id]
|
| 145 |
-
drug_emb = embeddings[drug_idx].reshape(1, -1)
|
| 146 |
-
|
| 147 |
-
# Compute similarities to all proteins
|
| 148 |
-
predictions = []
|
| 149 |
-
for _, protein_row in protein_nodes.iterrows():
|
| 150 |
-
protein_id = protein_row['protein_id']
|
| 151 |
-
protein_name = protein_row['protein_name']
|
| 152 |
-
|
| 153 |
-
# Skip known targets
|
| 154 |
-
if protein_id in known_targets:
|
| 155 |
-
continue
|
| 156 |
-
|
| 157 |
-
# Get protein embedding
|
| 158 |
-
if protein_id not in node_to_idx:
|
| 159 |
-
continue
|
| 160 |
-
|
| 161 |
-
protein_idx = node_to_idx[protein_id]
|
| 162 |
-
protein_emb = embeddings[protein_idx].reshape(1, -1)
|
| 163 |
-
|
| 164 |
-
# Calculate similarity
|
| 165 |
-
sim = cosine_similarity(drug_emb, protein_emb)[0][0]
|
| 166 |
-
|
| 167 |
-
predictions.append({
|
| 168 |
-
'Predicted Target': protein_name,
|
| 169 |
-
'ChEMBL ID': protein_id,
|
| 170 |
-
'Similarity': f"{sim:.4f}",
|
| 171 |
-
'Confidence': 'High' if sim > 0.5 else 'Medium' if sim > 0.45 else 'Low'
|
| 172 |
-
})
|
| 173 |
-
|
| 174 |
-
# Sort and return top-k
|
| 175 |
-
predictions_df = pd.DataFrame(predictions)
|
| 176 |
-
if len(predictions_df) == 0:
|
| 177 |
-
return pd.DataFrame(columns=['Predicted Target', 'Similarity', 'Confidence'])
|
| 178 |
-
|
| 179 |
-
predictions_df['Similarity_Float'] = predictions_df['Similarity'].astype(float)
|
| 180 |
-
predictions_df = predictions_df.sort_values('Similarity_Float', ascending=False).head(top_k)
|
| 181 |
-
|
| 182 |
-
return predictions_df[['Predicted Target', 'ChEMBL ID', 'Similarity', 'Confidence']]
|
| 183 |
-
|
| 184 |
-
def get_predicted_effects(drug_internal_id, top_k=10):
|
| 185 |
-
"""Get predicted novel clinical effects"""
|
| 186 |
-
if drug_internal_id is None:
|
| 187 |
-
return pd.DataFrame()
|
| 188 |
-
|
| 189 |
-
# Get known effects to filter out
|
| 190 |
-
known_effects = set(drug_effects[
|
| 191 |
-
drug_effects['drug_internal_id'] == drug_internal_id
|
| 192 |
-
]['effect_id'].values)
|
| 193 |
-
|
| 194 |
-
# Check if drug is in embedding space
|
| 195 |
-
if drug_internal_id not in node_to_idx:
|
| 196 |
-
return pd.DataFrame(columns=['Predicted Effect', 'Similarity', 'Confidence'])
|
| 197 |
-
|
| 198 |
-
# Get drug embedding
|
| 199 |
-
drug_idx = node_to_idx[drug_internal_id]
|
| 200 |
-
drug_emb = embeddings[drug_idx].reshape(1, -1)
|
| 201 |
-
|
| 202 |
-
# Compute similarities to all effects
|
| 203 |
-
predictions = []
|
| 204 |
-
unique_effects = drug_effects[['effect_id', 'effect_name']].drop_duplicates()
|
| 205 |
-
|
| 206 |
-
for _, effect_row in unique_effects.iterrows():
|
| 207 |
-
effect_id = effect_row['effect_id']
|
| 208 |
-
effect_name = effect_row['effect_name']
|
| 209 |
-
|
| 210 |
-
# Skip known effects
|
| 211 |
-
if effect_id in known_effects:
|
| 212 |
-
continue
|
| 213 |
-
|
| 214 |
-
# Get effect embedding
|
| 215 |
-
if effect_id not in node_to_idx:
|
| 216 |
-
continue
|
| 217 |
-
|
| 218 |
-
effect_idx = node_to_idx[effect_id]
|
| 219 |
-
effect_emb = embeddings[effect_idx].reshape(1, -1)
|
| 220 |
-
|
| 221 |
-
# Calculate similarity
|
| 222 |
-
sim = cosine_similarity(drug_emb, effect_emb)[0][0]
|
| 223 |
-
|
| 224 |
-
predictions.append({
|
| 225 |
-
'Predicted Effect': effect_name,
|
| 226 |
-
'MeSH ID': effect_id,
|
| 227 |
-
'Similarity': f"{sim:.4f}",
|
| 228 |
-
'Confidence': 'High' if sim > 0.5 else 'Medium' if sim > 0.45 else 'Low'
|
| 229 |
-
})
|
| 230 |
-
|
| 231 |
-
# Sort and return top-k
|
| 232 |
-
predictions_df = pd.DataFrame(predictions)
|
| 233 |
-
if len(predictions_df) == 0:
|
| 234 |
-
return pd.DataFrame(columns=['Predicted Effect', 'Similarity', 'Confidence'])
|
| 235 |
-
|
| 236 |
-
predictions_df['Similarity_Float'] = predictions_df['Similarity'].astype(float)
|
| 237 |
-
predictions_df = predictions_df.sort_values('Similarity_Float', ascending=False).head(top_k)
|
| 238 |
-
|
| 239 |
-
return predictions_df[['Predicted Effect', 'MeSH ID', 'Similarity', 'Confidence']]
|
| 240 |
-
|
| 241 |
-
def create_network_visualization(drug_internal_id, show_known=True, show_predicted=True, max_nodes=20):
|
| 242 |
-
"""Create interactive network visualization using Plotly"""
|
| 243 |
-
if drug_internal_id is None:
|
| 244 |
-
return None
|
| 245 |
-
|
| 246 |
-
# Get drug info
|
| 247 |
-
drug_row = drug_nodes[drug_nodes['drug_internal_id'] == drug_internal_id]
|
| 248 |
-
if len(drug_row) == 0:
|
| 249 |
-
return None
|
| 250 |
-
|
| 251 |
-
drug_name = drug_row.iloc[0]['drug_name']
|
| 252 |
-
drug_chembl_id = drug_row.iloc[0]['drug_id']
|
| 253 |
-
|
| 254 |
-
# Create network
|
| 255 |
-
G = nx.Graph()
|
| 256 |
-
|
| 257 |
-
# Add central drug node
|
| 258 |
-
G.add_node(drug_name, node_type='drug', color='#FF6B6B', size=30)
|
| 259 |
-
|
| 260 |
-
edge_traces = []
|
| 261 |
-
node_texts = []
|
| 262 |
-
|
| 263 |
-
# Add known targets
|
| 264 |
-
if show_known:
|
| 265 |
-
known_targets_df = get_known_targets(drug_internal_id)
|
| 266 |
-
for idx, row in known_targets_df.head(max_nodes // 2).iterrows():
|
| 267 |
-
target_name = row['Target Protein'][:30]
|
| 268 |
-
G.add_node(target_name, node_type='protein_known', color='#4ECDC4', size=15)
|
| 269 |
-
G.add_edge(drug_name, target_name, edge_type='known', color='#95E1D3', width=3)
|
| 270 |
-
|
| 271 |
-
# Add predicted targets
|
| 272 |
-
if show_predicted:
|
| 273 |
-
predicted_targets_df = get_predicted_targets(drug_internal_id, top_k=max_nodes // 2)
|
| 274 |
-
for idx, row in predicted_targets_df.iterrows():
|
| 275 |
-
target_name = row['Predicted Target'][:30]
|
| 276 |
-
similarity = float(row['Similarity'])
|
| 277 |
-
G.add_node(target_name, node_type='protein_predicted', color='#A8E6CF', size=10)
|
| 278 |
-
G.add_edge(drug_name, target_name, edge_type='predicted',
|
| 279 |
-
color='#DCEDC8', width=1.5, similarity=similarity)
|
| 280 |
-
|
| 281 |
-
# Add known effects
|
| 282 |
-
if show_known:
|
| 283 |
-
known_effects_df = get_known_effects(drug_internal_id)
|
| 284 |
-
for idx, row in known_effects_df.head(max_nodes // 3).iterrows():
|
| 285 |
-
effect_name = row['Clinical Effect'][:30]
|
| 286 |
-
G.add_node(effect_name, node_type='effect_known', color='#FFD93D', size=15)
|
| 287 |
-
G.add_edge(drug_name, effect_name, edge_type='known_effect', color='#FCF4A3', width=3)
|
| 288 |
-
|
| 289 |
-
# Add predicted effects
|
| 290 |
-
if show_predicted:
|
| 291 |
-
predicted_effects_df = get_predicted_effects(drug_internal_id, top_k=max_nodes // 3)
|
| 292 |
-
for idx, row in predicted_effects_df.iterrows():
|
| 293 |
-
effect_name = row['Predicted Effect'][:30]
|
| 294 |
-
similarity = float(row['Similarity'])
|
| 295 |
-
G.add_node(effect_name, node_type='effect_predicted', color='#FFF9A3', size=10)
|
| 296 |
-
G.add_edge(drug_name, effect_name, edge_type='predicted_effect',
|
| 297 |
-
color='#FFFACD', width=1.5, similarity=similarity)
|
| 298 |
-
|
| 299 |
-
# Calculate layout
|
| 300 |
-
pos = nx.spring_layout(G, k=2, iterations=50, seed=42)
|
| 301 |
-
|
| 302 |
-
# Create edge traces
|
| 303 |
-
edge_traces = []
|
| 304 |
-
for edge in G.edges(data=True):
|
| 305 |
-
x0, y0 = pos[edge[0]]
|
| 306 |
-
x1, y1 = pos[edge[1]]
|
| 307 |
-
|
| 308 |
-
edge_trace = go.Scatter(
|
| 309 |
-
x=[x0, x1, None],
|
| 310 |
-
y=[y0, y1, None],
|
| 311 |
-
mode='lines',
|
| 312 |
-
line=dict(
|
| 313 |
-
width=edge[2].get('width', 1),
|
| 314 |
-
color=edge[2].get('color', '#888')
|
| 315 |
-
),
|
| 316 |
-
hoverinfo='none',
|
| 317 |
-
showlegend=False
|
| 318 |
-
)
|
| 319 |
-
edge_traces.append(edge_trace)
|
| 320 |
-
|
| 321 |
-
# Create node trace
|
| 322 |
-
node_x = []
|
| 323 |
-
node_y = []
|
| 324 |
-
node_color = []
|
| 325 |
-
node_size = []
|
| 326 |
-
node_text = []
|
| 327 |
-
|
| 328 |
-
for node in G.nodes(data=True):
|
| 329 |
-
x, y = pos[node[0]]
|
| 330 |
-
node_x.append(x)
|
| 331 |
-
node_y.append(y)
|
| 332 |
-
node_color.append(node[1].get('color', '#888'))
|
| 333 |
-
node_size.append(node[1].get('size', 10))
|
| 334 |
-
|
| 335 |
-
# Create hover text
|
| 336 |
-
node_type = node[1].get('node_type', 'unknown')
|
| 337 |
-
if node_type == 'drug':
|
| 338 |
-
text = f"<b>{node[0]}</b><br>Type: Drug<br>ChEMBL: {drug_chembl_id}"
|
| 339 |
-
elif 'protein' in node_type:
|
| 340 |
-
text = f"<b>{node[0]}</b><br>Type: Protein Target<br>{'Known' if 'known' in node_type else 'Predicted'}"
|
| 341 |
-
elif 'effect' in node_type:
|
| 342 |
-
text = f"<b>{node[0]}</b><br>Type: Clinical Effect<br>{'Known' if 'known' in node_type else 'Predicted'}"
|
| 343 |
-
else:
|
| 344 |
-
text = f"<b>{node[0]}</b>"
|
| 345 |
-
|
| 346 |
-
node_text.append(text)
|
| 347 |
-
|
| 348 |
-
node_trace = go.Scatter(
|
| 349 |
-
x=node_x,
|
| 350 |
-
y=node_y,
|
| 351 |
-
mode='markers+text',
|
| 352 |
-
text=[node[0] for node in G.nodes()],
|
| 353 |
-
textposition='top center',
|
| 354 |
-
textfont=dict(size=8),
|
| 355 |
-
hovertext=node_text,
|
| 356 |
-
hoverinfo='text',
|
| 357 |
-
marker=dict(
|
| 358 |
-
size=node_size,
|
| 359 |
-
color=node_color,
|
| 360 |
-
line=dict(width=2, color='white')
|
| 361 |
-
),
|
| 362 |
-
showlegend=False
|
| 363 |
-
)
|
| 364 |
-
|
| 365 |
-
# Create figure
|
| 366 |
-
fig = go.Figure(data=edge_traces + [node_trace])
|
| 367 |
-
|
| 368 |
-
fig.update_layout(
|
| 369 |
-
title=dict(
|
| 370 |
-
text=f"Knowledge Graph for {drug_name}",
|
| 371 |
-
font=dict(size=20)
|
| 372 |
-
),
|
| 373 |
-
showlegend=False,
|
| 374 |
-
hovermode='closest',
|
| 375 |
-
margin=dict(b=0, l=0, r=0, t=40),
|
| 376 |
-
xaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
|
| 377 |
-
yaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
|
| 378 |
-
plot_bgcolor='rgba(240,240,240,0.9)',
|
| 379 |
-
height=700
|
| 380 |
-
)
|
| 381 |
-
|
| 382 |
-
# Add legend manually
|
| 383 |
-
fig.add_annotation(
|
| 384 |
-
text="<b>Legend:</b><br>" +
|
| 385 |
-
"🔴 Drug | 🔵 Known Target | 🟢 Predicted Target<br>" +
|
| 386 |
-
"🟡 Known Effect | 🟨 Predicted Effect",
|
| 387 |
-
xref="paper", yref="paper",
|
| 388 |
-
x=0.02, y=0.98,
|
| 389 |
-
showarrow=False,
|
| 390 |
-
bgcolor="white",
|
| 391 |
-
bordercolor="black",
|
| 392 |
-
borderwidth=1,
|
| 393 |
-
font=dict(size=10),
|
| 394 |
-
align="left"
|
| 395 |
-
)
|
| 396 |
-
|
| 397 |
-
return fig
|
| 398 |
-
|
| 399 |
-
def analyze_drug(search_query, drug_selection, show_known, show_predicted, max_nodes):
|
| 400 |
-
"""Main analysis function"""
|
| 401 |
-
try:
|
| 402 |
-
if drug_selection is None:
|
| 403 |
-
return (
|
| 404 |
-
"Please search and select a drug from the dropdown",
|
| 405 |
-
pd.DataFrame(),
|
| 406 |
-
pd.DataFrame(),
|
| 407 |
-
pd.DataFrame(),
|
| 408 |
-
pd.DataFrame(),
|
| 409 |
-
None
|
| 410 |
-
)
|
| 411 |
-
|
| 412 |
-
# Extract drug_internal_id from selection
|
| 413 |
-
drug_internal_id = drug_selection
|
| 414 |
-
|
| 415 |
-
# Get all data with error handling
|
| 416 |
-
info = get_drug_info(drug_internal_id)
|
| 417 |
-
known_targets = get_known_targets(drug_internal_id)
|
| 418 |
-
known_effects = get_known_effects(drug_internal_id)
|
| 419 |
-
pred_targets = get_predicted_targets(drug_internal_id, top_k=15)
|
| 420 |
-
pred_effects = get_predicted_effects(drug_internal_id, top_k=15)
|
| 421 |
-
network = create_network_visualization(drug_internal_id, show_known, show_predicted, max_nodes)
|
| 422 |
-
|
| 423 |
-
return info, known_targets, known_effects, pred_targets, pred_effects, network
|
| 424 |
-
|
| 425 |
-
except Exception as e:
|
| 426 |
-
error_msg = f"⚠️ Error analyzing drug: {str(e)}\n\nPlease try selecting a different drug or check the console for details."
|
| 427 |
-
print(f"Error in analyze_drug: {e}")
|
| 428 |
-
import traceback
|
| 429 |
-
traceback.print_exc()
|
| 430 |
-
|
| 431 |
-
return (
|
| 432 |
-
error_msg,
|
| 433 |
-
pd.DataFrame(),
|
| 434 |
-
pd.DataFrame(),
|
| 435 |
-
pd.DataFrame(),
|
| 436 |
-
pd.DataFrame(),
|
| 437 |
-
None
|
| 438 |
-
)
|
| 439 |
-
|
| 440 |
-
# Create Gradio interface
|
| 441 |
-
with gr.Blocks(title="Pharmacology Knowledge Graph Explorer", theme=gr.themes.Soft()) as demo:
|
| 442 |
-
gr.Markdown(
|
| 443 |
-
"""
|
| 444 |
-
# 💊 Pharmacology Knowledge Graph Explorer
|
| 445 |
-
|
| 446 |
-
Explore drug-target-effect relationships using AI-powered predictions from a TransE knowledge graph model.
|
| 447 |
-
|
| 448 |
-
**Features:**
|
| 449 |
-
- 🔍 Search **2,526** FDA-approved drugs
|
| 450 |
-
- 🎯 View known and predicted protein targets
|
| 451 |
-
- 💉 Discover potential therapeutic uses (drug repurposing)
|
| 452 |
-
- 🕸️ Interactive network visualization
|
| 453 |
-
|
| 454 |
-
---
|
| 455 |
-
"""
|
| 456 |
-
)
|
| 457 |
-
|
| 458 |
-
with gr.Row():
|
| 459 |
-
with gr.Column(scale=1):
|
| 460 |
-
gr.Markdown("### 🔍 Drug Search")
|
| 461 |
-
search_box = gr.Textbox(
|
| 462 |
-
label="Search by drug name or ChEMBL ID",
|
| 463 |
-
placeholder="e.g., Aspirin, Morphine, CHEMBL25",
|
| 464 |
-
info="Type to search, then select from dropdown"
|
| 465 |
-
)
|
| 466 |
-
|
| 467 |
-
drug_dropdown = gr.Dropdown(
|
| 468 |
-
label="Select Drug",
|
| 469 |
-
choices=[],
|
| 470 |
-
interactive=True
|
| 471 |
-
)
|
| 472 |
-
|
| 473 |
-
gr.Markdown("### ⚙️ Visualization Settings")
|
| 474 |
-
show_known_checkbox = gr.Checkbox(label="Show known interactions", value=True)
|
| 475 |
-
show_predicted_checkbox = gr.Checkbox(label="Show predicted interactions", value=True)
|
| 476 |
-
max_nodes_slider = gr.Slider(
|
| 477 |
-
minimum=10, maximum=50, value=20, step=5,
|
| 478 |
-
label="Max nodes to display"
|
| 479 |
-
)
|
| 480 |
-
|
| 481 |
-
analyze_btn = gr.Button("🔬 Analyze Drug", variant="primary", size="lg")
|
| 482 |
-
|
| 483 |
-
with gr.Column(scale=2):
|
| 484 |
-
drug_info = gr.Markdown("### Select a drug to begin analysis")
|
| 485 |
-
|
| 486 |
-
gr.Markdown("---")
|
| 487 |
-
|
| 488 |
-
with gr.Row():
|
| 489 |
-
with gr.Column():
|
| 490 |
-
gr.Markdown("### 🎯 Known Protein Targets")
|
| 491 |
-
known_targets_table = gr.Dataframe(
|
| 492 |
-
headers=['Target Protein', 'ChEMBL ID', 'pChEMBL (max)', 'pChEMBL (avg)', 'Measurements'],
|
| 493 |
-
interactive=False
|
| 494 |
-
)
|
| 495 |
-
|
| 496 |
-
with gr.Column():
|
| 497 |
-
gr.Markdown("### 🔮 Predicted Novel Targets")
|
| 498 |
-
predicted_targets_table = gr.Dataframe(
|
| 499 |
-
headers=['Predicted Target', 'ChEMBL ID', 'Similarity', 'Confidence'],
|
| 500 |
-
interactive=False
|
| 501 |
-
)
|
| 502 |
-
|
| 503 |
-
gr.Markdown("---")
|
| 504 |
-
|
| 505 |
-
with gr.Row():
|
| 506 |
-
with gr.Column():
|
| 507 |
-
gr.Markdown("### 💉 Known Clinical Effects")
|
| 508 |
-
known_effects_table = gr.Dataframe(
|
| 509 |
-
headers=['Clinical Effect', 'MeSH ID', 'Phase', 'References'],
|
| 510 |
-
interactive=False
|
| 511 |
-
)
|
| 512 |
-
|
| 513 |
-
with gr.Column():
|
| 514 |
-
gr.Markdown("### 💡 Predicted Novel Effects (Repurposing)")
|
| 515 |
-
predicted_effects_table = gr.Dataframe(
|
| 516 |
-
headers=['Predicted Effect', 'MeSH ID', 'Similarity', 'Confidence'],
|
| 517 |
-
interactive=False
|
| 518 |
-
)
|
| 519 |
-
|
| 520 |
-
gr.Markdown("---")
|
| 521 |
-
|
| 522 |
-
gr.Markdown("### 🕸️ Interactive Knowledge Graph")
|
| 523 |
-
network_plot = gr.Plot()
|
| 524 |
-
|
| 525 |
-
gr.Markdown(
|
| 526 |
-
"""
|
| 527 |
-
---
|
| 528 |
-
|
| 529 |
-
### 📊 About the Model
|
| 530 |
-
|
| 531 |
-
This app uses a **TransE knowledge graph embedding model** trained on:
|
| 532 |
-
- **2,526** FDA-approved drugs
|
| 533 |
-
- **1,156** human protein targets (with ESM-2 embeddings)
|
| 534 |
-
- **1,065** clinical indications
|
| 535 |
-
- **18,789** total known links
|
| 536 |
-
|
| 537 |
-
**Prediction method:** Cosine similarity in learned embedding space
|
| 538 |
-
**Model performance:** ~90% precision on top-50 predictions
|
| 539 |
-
|
| 540 |
-
**By:** Youssef Abo-Dahab, Pharm.D.
|
| 541 |
-
**AICD3 M.S. Candidate, UCSF** | October 2025
|
| 542 |
-
|
| 543 |
-
[GitHub Repository](https://github.com/JoeVonDahab/pharmacology-graph)
|
| 544 |
-
|
| 545 |
-
---
|
| 546 |
-
**Disclaimer:** This is a research tool for exploratory analysis only. Predictions should be validated experimentally. Not for clinical use.
|
| 547 |
-
"""
|
| 548 |
-
)
|
| 549 |
-
|
| 550 |
-
# Event handlers
|
| 551 |
-
# Store mapping globally to avoid re-searching
|
| 552 |
-
drug_display_to_id = gr.State({})
|
| 553 |
-
selected_drug_id = gr.State()
|
| 554 |
-
|
| 555 |
-
def update_dropdown(search_query):
|
| 556 |
-
if not search_query or len(search_query) < 1:
|
| 557 |
-
return gr.update(choices=[]), {}
|
| 558 |
-
|
| 559 |
-
results = search_drugs(search_query)
|
| 560 |
-
print(f"Search '{search_query}' found {len(results)} results") # Debug output
|
| 561 |
-
|
| 562 |
-
# Create mapping: display_name -> internal_id
|
| 563 |
-
mapping = {display: internal_id for display, internal_id in results}
|
| 564 |
-
choices = list(mapping.keys())
|
| 565 |
-
|
| 566 |
-
print(f"Returning choices: {choices[:3]}..." if len(choices) > 3 else f"Returning choices: {choices}") # Debug
|
| 567 |
-
return gr.update(choices=choices, value=None), mapping
|
| 568 |
-
|
| 569 |
-
def store_selection(dropdown_value, mapping):
|
| 570 |
-
if not dropdown_value or not mapping:
|
| 571 |
-
return None
|
| 572 |
-
|
| 573 |
-
# Get internal_id from mapping
|
| 574 |
-
return mapping.get(dropdown_value, None)
|
| 575 |
-
|
| 576 |
-
search_box.change(
|
| 577 |
-
fn=update_dropdown,
|
| 578 |
-
inputs=[search_box],
|
| 579 |
-
outputs=[drug_dropdown, drug_display_to_id]
|
| 580 |
-
)
|
| 581 |
-
|
| 582 |
-
drug_dropdown.change(
|
| 583 |
-
fn=store_selection,
|
| 584 |
-
inputs=[drug_dropdown, drug_display_to_id],
|
| 585 |
-
outputs=[selected_drug_id]
|
| 586 |
-
)
|
| 587 |
-
|
| 588 |
-
analyze_btn.click(
|
| 589 |
-
fn=analyze_drug,
|
| 590 |
-
inputs=[
|
| 591 |
-
search_box,
|
| 592 |
-
selected_drug_id,
|
| 593 |
-
show_known_checkbox,
|
| 594 |
-
show_predicted_checkbox,
|
| 595 |
-
max_nodes_slider
|
| 596 |
-
],
|
| 597 |
-
outputs=[
|
| 598 |
-
drug_info,
|
| 599 |
-
known_targets_table,
|
| 600 |
-
known_effects_table,
|
| 601 |
-
predicted_targets_table,
|
| 602 |
-
predicted_effects_table,
|
| 603 |
-
network_plot
|
| 604 |
-
]
|
| 605 |
-
)
|
| 606 |
-
|
| 607 |
-
# Launch
|
| 608 |
-
if __name__ == "__main__":
|
| 609 |
-
demo.launch(share=False, server_name="0.0.0.0", server_port=7860)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cleanup.sh
DELETED
|
@@ -1,59 +0,0 @@
|
|
| 1 |
-
#!/bin/bash
|
| 2 |
-
|
| 3 |
-
# Cleanup script to remove unnecessary files for end users
|
| 4 |
-
# This keeps only essential files needed to run the Gradio app
|
| 5 |
-
|
| 6 |
-
echo "🧹 Pharmacology Graph - Cleanup Script"
|
| 7 |
-
echo "======================================"
|
| 8 |
-
echo ""
|
| 9 |
-
echo "This will remove development/duplicate files not needed to run the app."
|
| 10 |
-
echo "Essential files (app.py, CSV data, requirements_app.txt) will be kept."
|
| 11 |
-
echo ""
|
| 12 |
-
read -p "Continue? (y/n) " -n 1 -r
|
| 13 |
-
echo ""
|
| 14 |
-
|
| 15 |
-
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
| 16 |
-
echo "Cancelled."
|
| 17 |
-
exit 0
|
| 18 |
-
fi
|
| 19 |
-
|
| 20 |
-
echo ""
|
| 21 |
-
echo "Removing unnecessary files..."
|
| 22 |
-
|
| 23 |
-
# Documentation duplicates
|
| 24 |
-
rm -f BUGFIX_SUMMARY.md && echo " ✓ Removed BUGFIX_SUMMARY.md"
|
| 25 |
-
rm -f APP_SUMMARY.md && echo " ✓ Removed APP_SUMMARY.md"
|
| 26 |
-
rm -f CHECKLIST.md && echo " ✓ Removed CHECKLIST.md"
|
| 27 |
-
|
| 28 |
-
# Duplicate/old scripts
|
| 29 |
-
rm -f run_app.sh && echo " ✓ Removed run_app.sh (use start_app.sh instead)"
|
| 30 |
-
rm -f test_search.py && echo " ✓ Removed test_search.py"
|
| 31 |
-
|
| 32 |
-
# Old/temporary files (if they exist)
|
| 33 |
-
rm -f main.py && echo " ✓ Removed main.py"
|
| 34 |
-
rm -f .python-version && echo " ✓ Removed .python-version"
|
| 35 |
-
|
| 36 |
-
# Image outputs (can regenerate from notebook)
|
| 37 |
-
rm -f *.png && echo " ✓ Removed PNG images"
|
| 38 |
-
|
| 39 |
-
# Pickle files (can regenerate from notebook)
|
| 40 |
-
rm -f *.pkl && echo " ✓ Removed PKL files"
|
| 41 |
-
|
| 42 |
-
# Intermediate CSV files (not needed for app)
|
| 43 |
-
rm -f drug_mechanism_filtered.csv && echo " ✓ Removed drug_mechanism_filtered.csv"
|
| 44 |
-
rm -f drug_warnings.csv && echo " ✓ Removed drug_warnings.csv"
|
| 45 |
-
rm -f edges_drug_protein.csv && echo " ✓ Removed edges_drug_protein.csv"
|
| 46 |
-
rm -f proteins_for_embedding.csv && echo " ✓ Removed proteins_for_embedding.csv"
|
| 47 |
-
rm -f top_50_predicted_drug_targets.csv && echo " ✓ Removed top_50_predicted_drug_targets.csv (duplicate)"
|
| 48 |
-
|
| 49 |
-
echo ""
|
| 50 |
-
echo "✅ Cleanup complete!"
|
| 51 |
-
echo ""
|
| 52 |
-
echo "Remaining essential files:"
|
| 53 |
-
ls -lh *.py *.txt *.sh *.md 2>/dev/null | awk '{print " - " $9 " (" $5 ")"}'
|
| 54 |
-
echo ""
|
| 55 |
-
echo "Data files:"
|
| 56 |
-
ls -lh *.csv *.npy 2>/dev/null | awk '{print " - " $9 " (" $5 ")"}'
|
| 57 |
-
echo ""
|
| 58 |
-
echo "Total size:"
|
| 59 |
-
du -sh . | awk '{print " " $1}'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
code.ipynb
DELETED
|
The diff for this file is too large to render.
See raw diff
|
|
|
drug_effects.csv
DELETED
|
The diff for this file is too large to render.
See raw diff
|
|
|
drug_nodes.csv
DELETED
|
The diff for this file is too large to render.
See raw diff
|
|
|
drugs_interactions.csv
DELETED
|
The diff for this file is too large to render.
See raw diff
|
|
|
graph_embeddings.npy
DELETED
|
@@ -1,3 +0,0 @@
|
|
| 1 |
-
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:a5bfc5b74dcc2a159c88885b92432888d42a32101c34d7490051865be5d22dab
|
| 3 |
-
size 2663040
|
|
|
|
|
|
|
|
|
|
|
|
index.html
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="utf-8" />
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
| 6 |
+
<title>Pharmacology Graph — Drug · Disease · Target Explorer</title>
|
| 7 |
+
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>💊</text></svg>" />
|
| 8 |
+
<link rel="stylesheet" href="style.css?v=p5" />
|
| 9 |
+
</head>
|
| 10 |
+
<body>
|
| 11 |
+
<header class="site-header">
|
| 12 |
+
<div class="wrap">
|
| 13 |
+
<h1>💊 Pharmacology Graph Explorer</h1>
|
| 14 |
+
<p class="tagline">
|
| 15 |
+
Search a <span class="chip drug">Drug</span> to see its predicted targets & indications, or a
|
| 16 |
+
<span class="chip ind">Indication</span> / <span class="chip prot">Protein</span> to see the drugs most likely
|
| 17 |
+
linked to it — each flagged <span class="badge known">known</span> or <span class="badge novel">novel</span>.
|
| 18 |
+
</p>
|
| 19 |
+
<p class="meta-line" id="meta-line"></p>
|
| 20 |
+
<p class="meta-line" id="metrics-note"></p>
|
| 21 |
+
</div>
|
| 22 |
+
</header>
|
| 23 |
+
|
| 24 |
+
<main class="wrap">
|
| 25 |
+
<section class="search-box">
|
| 26 |
+
<label for="search" class="sr-only">Search</label>
|
| 27 |
+
<input id="search" type="text" autocomplete="off" spellcheck="false"
|
| 28 |
+
placeholder="Search a drug, disease/indication, or protein (e.g. sunitinib, breast neoplasms, CHEMBL231)…" />
|
| 29 |
+
<ul id="suggestions" class="suggestions" hidden></ul>
|
| 30 |
+
</section>
|
| 31 |
+
|
| 32 |
+
<section id="empty-state" class="empty">
|
| 33 |
+
<p>Start typing above. <span class="hint">Drugs · Indications · Proteins — all searchable, both directions.</span></p>
|
| 34 |
+
<div class="examples" id="examples"></div>
|
| 35 |
+
</section>
|
| 36 |
+
|
| 37 |
+
<section id="result" class="result" hidden>
|
| 38 |
+
<div class="drug-head">
|
| 39 |
+
<div>
|
| 40 |
+
<span class="chip" id="type-chip"></span>
|
| 41 |
+
<h2 id="drug-name"></h2>
|
| 42 |
+
<a id="drug-link" class="ext" target="_blank" rel="noopener"></a>
|
| 43 |
+
</div>
|
| 44 |
+
<div class="stat-cards" id="stat-cards"></div>
|
| 45 |
+
</div>
|
| 46 |
+
|
| 47 |
+
<div class="controls">
|
| 48 |
+
<div class="tabs" id="tabs" role="tablist"></div>
|
| 49 |
+
<div class="filters">
|
| 50 |
+
<div class="chips" id="status-filter">
|
| 51 |
+
<button class="chip active" data-status="all">All</button>
|
| 52 |
+
<button class="chip" data-status="novel">Novel only</button>
|
| 53 |
+
<button class="chip" data-status="known">Known only</button>
|
| 54 |
+
</div>
|
| 55 |
+
<input id="table-filter" class="table-filter" type="text" placeholder="Filter rows…" />
|
| 56 |
+
<div class="downloads">
|
| 57 |
+
<button id="dl-csv" class="dl">⬇ CSV</button>
|
| 58 |
+
<button id="dl-json" class="dl">⬇ JSON</button>
|
| 59 |
+
</div>
|
| 60 |
+
</div>
|
| 61 |
+
</div>
|
| 62 |
+
|
| 63 |
+
<table class="pred-table">
|
| 64 |
+
<thead>
|
| 65 |
+
<tr><th class="c-rank">#</th><th id="th-target">Target</th><th>ID</th><th class="c-score">Score</th><th class="c-status">Status</th></tr>
|
| 66 |
+
</thead>
|
| 67 |
+
<tbody id="pred-body"></tbody>
|
| 68 |
+
</table>
|
| 69 |
+
<p id="no-rows" class="no-rows" hidden>No rows match the current filter.</p>
|
| 70 |
+
</section>
|
| 71 |
+
</main>
|
| 72 |
+
|
| 73 |
+
<footer class="site-footer">
|
| 74 |
+
<div class="wrap">
|
| 75 |
+
<p>
|
| 76 |
+
Predictions are model outputs for research exploration only — not clinical or experimental validation.
|
| 77 |
+
Score is the model's relative confidence within each ranking (1.0 = top). Download full tables:
|
| 78 |
+
<a href="https://joevondahab.github.io/pharmacology-graph/data/predictions_drug_protein.csv">drug–protein CSV</a> ·
|
| 79 |
+
<a href="https://joevondahab.github.io/pharmacology-graph/data/predictions_drug_indication.csv">drug–indication CSV</a>.
|
| 80 |
+
</p>
|
| 81 |
+
<p class="src">Model: Ablation 2 “No Drug Graphs” (~3.29M params), faithfully reconstructed from
|
| 82 |
+
<a href="https://arxiv.org/abs/2603.01537" target="_blank" rel="noopener">arXiv:2603.01537</a> —
|
| 83 |
+
learnable drug embeddings + ESM-2 proteins + heterogeneous GraphSAGE message passing.</p>
|
| 84 |
+
</div>
|
| 85 |
+
</footer>
|
| 86 |
+
|
| 87 |
+
<script src="app.js?v=p5"></script>
|
| 88 |
+
</body>
|
| 89 |
+
</html>
|
node_to_idx.npy
DELETED
|
@@ -1,3 +0,0 @@
|
|
| 1 |
-
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:b88d5415499ea4b8732915f1459f14b330c79b377886ee2137b2d65f3131a15d
|
| 3 |
-
size 55513
|
|
|
|
|
|
|
|
|
|
|
|
protein_nodes_with_embeddings.csv
DELETED
|
The diff for this file is too large to render.
See raw diff
|
|
|
pyproject.toml
DELETED
|
@@ -1,7 +0,0 @@
|
|
| 1 |
-
[project]
|
| 2 |
-
name = "pharmacology-graph"
|
| 3 |
-
version = "0.1.0"
|
| 4 |
-
description = "Add your description here"
|
| 5 |
-
readme = "README.md"
|
| 6 |
-
requires-python = ">=3.11"
|
| 7 |
-
dependencies = []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
requirements.txt
DELETED
|
@@ -1,11 +0,0 @@
|
|
| 1 |
-
# Hugging Face Spaces Requirements
|
| 2 |
-
# Updated versions confirmed working (2025-10-11)
|
| 3 |
-
|
| 4 |
-
gradio==4.44.1
|
| 5 |
-
pandas==2.3.3
|
| 6 |
-
numpy>=1.26.0,<2.0
|
| 7 |
-
plotly==6.3.1
|
| 8 |
-
networkx==3.2.1
|
| 9 |
-
scikit-learn==1.4.0
|
| 10 |
-
|
| 11 |
-
huggingface-hub==0.23.5
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
requirements_app.txt
DELETED
|
@@ -1,14 +0,0 @@
|
|
| 1 |
-
# Updated versions after testing (2025-01-24)
|
| 2 |
-
# These versions are confirmed to work together without conflicts
|
| 3 |
-
|
| 4 |
-
gradio==4.44.1
|
| 5 |
-
pandas==2.3.3
|
| 6 |
-
numpy>=1.26.0,<2.0 # NumPy 2.x breaks compatibility with pandas/numexpr
|
| 7 |
-
plotly==6.3.1
|
| 8 |
-
networkx==3.2.1
|
| 9 |
-
scikit-learn==1.4.0==4.44.0
|
| 10 |
-
pandas==2.2.0
|
| 11 |
-
numpy==1.26.3
|
| 12 |
-
plotly==5.18.0
|
| 13 |
-
networkx==3.2.1
|
| 14 |
-
scikit-learn==1.4.0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
start_app.sh
DELETED
|
@@ -1,24 +0,0 @@
|
|
| 1 |
-
#!/bin/bash
|
| 2 |
-
|
| 3 |
-
echo "🚀 Starting Pharmacology Graph App"
|
| 4 |
-
echo "=================================="
|
| 5 |
-
echo ""
|
| 6 |
-
|
| 7 |
-
# Kill any existing instances
|
| 8 |
-
pkill -f "python.*app.py" 2>/dev/null
|
| 9 |
-
sleep 1
|
| 10 |
-
|
| 11 |
-
# Clear port if needed
|
| 12 |
-
lsof -ti:7860 | xargs kill -9 2>/dev/null
|
| 13 |
-
sleep 1
|
| 14 |
-
|
| 15 |
-
echo "✓ Port 7860 ready"
|
| 16 |
-
echo "✓ Starting app..."
|
| 17 |
-
echo ""
|
| 18 |
-
echo "Open in browser: http://localhost:7860"
|
| 19 |
-
echo "Press Ctrl+C to stop"
|
| 20 |
-
echo ""
|
| 21 |
-
|
| 22 |
-
# Start the app
|
| 23 |
-
cd /home/joe/projects/pharmacology-graph
|
| 24 |
-
python app.py
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
style.css
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
:root{
|
| 2 |
+
--bg:#0f1420; --panel:#171e2e; --panel2:#1f2840; --line:#2b3550;
|
| 3 |
+
--text:#e7ecf5; --muted:#9aa7c2; --accent:#5b8cff; --accent2:#7c5cff;
|
| 4 |
+
--known:#3fb27f; --known-bg:rgba(63,178,127,.14);
|
| 5 |
+
--novel:#e0a83b; --novel-bg:rgba(224,168,59,.14);
|
| 6 |
+
}
|
| 7 |
+
*{box-sizing:border-box}
|
| 8 |
+
body{margin:0;background:var(--bg);color:var(--text);
|
| 9 |
+
font:15px/1.5 system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif}
|
| 10 |
+
.wrap{max-width:960px;margin:0 auto;padding:0 20px}
|
| 11 |
+
.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0)}
|
| 12 |
+
a{color:var(--accent)}
|
| 13 |
+
.site-header{background:linear-gradient(160deg,#1a2236,#0f1420);
|
| 14 |
+
border-bottom:1px solid var(--line);padding:34px 0 26px}
|
| 15 |
+
h1{margin:0 0 6px;font-size:26px}
|
| 16 |
+
.tagline{margin:0;color:var(--muted);max-width:640px}
|
| 17 |
+
.tagline em{color:var(--text);font-style:normal;font-weight:600}
|
| 18 |
+
.meta-line{margin:10px 0 0;color:var(--muted);font-size:13px}
|
| 19 |
+
|
| 20 |
+
.search-box{position:relative;margin:26px 0 10px}
|
| 21 |
+
#search{width:100%;padding:15px 18px;font-size:16px;border-radius:12px;
|
| 22 |
+
background:var(--panel);border:1px solid var(--line);color:var(--text);outline:none}
|
| 23 |
+
#search:focus{border-color:var(--accent)}
|
| 24 |
+
.suggestions{list-style:none;margin:6px 0 0;padding:6px;position:absolute;z-index:20;
|
| 25 |
+
width:100%;background:var(--panel2);border:1px solid var(--line);border-radius:12px;
|
| 26 |
+
max-height:320px;overflow:auto;box-shadow:0 18px 40px rgba(0,0,0,.45)}
|
| 27 |
+
.suggestions li{padding:10px 12px;border-radius:8px;cursor:pointer;display:flex;
|
| 28 |
+
justify-content:space-between;gap:12px;align-items:center}
|
| 29 |
+
.suggestions li.active,.suggestions li:hover{background:var(--panel)}
|
| 30 |
+
.suggestions .sid{color:var(--muted);font-size:12px;font-variant-numeric:tabular-nums}
|
| 31 |
+
.suggestions mark{background:transparent;color:var(--accent);font-weight:700}
|
| 32 |
+
|
| 33 |
+
.empty{padding:40px 0;color:var(--muted);text-align:center}
|
| 34 |
+
.empty .hint{display:block;margin-top:8px;font-size:13px;opacity:.8}
|
| 35 |
+
.examples{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;margin-top:20px}
|
| 36 |
+
.examples button{background:var(--panel);border:1px solid var(--line);color:var(--text);
|
| 37 |
+
padding:7px 13px;border-radius:20px;cursor:pointer;font-size:13px}
|
| 38 |
+
.examples button:hover{border-color:var(--accent)}
|
| 39 |
+
|
| 40 |
+
.drug-head{display:flex;justify-content:space-between;gap:20px;flex-wrap:wrap;
|
| 41 |
+
align-items:flex-start;margin:8px 0 18px}
|
| 42 |
+
#drug-name{margin:0;font-size:23px}
|
| 43 |
+
.ext{font-size:13px}
|
| 44 |
+
.stat-cards{display:flex;gap:10px;flex-wrap:wrap}
|
| 45 |
+
.stat{background:var(--panel);border:1px solid var(--line);border-radius:10px;
|
| 46 |
+
padding:8px 14px;text-align:center;min-width:78px}
|
| 47 |
+
.stat b{display:block;font-size:19px}
|
| 48 |
+
.stat span{font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.04em}
|
| 49 |
+
.stat.known b{color:var(--known)} .stat.novel b{color:var(--novel)}
|
| 50 |
+
|
| 51 |
+
.controls{display:flex;justify-content:space-between;gap:14px;flex-wrap:wrap;
|
| 52 |
+
align-items:center;margin-bottom:12px}
|
| 53 |
+
.tabs{display:flex;gap:4px;background:var(--panel);padding:4px;border-radius:10px;border:1px solid var(--line)}
|
| 54 |
+
.tab{background:transparent;border:0;color:var(--muted);padding:8px 16px;border-radius:7px;cursor:pointer;font-size:14px}
|
| 55 |
+
.tab.active{background:var(--accent);color:#fff}
|
| 56 |
+
.filters{display:flex;gap:10px;align-items:center;flex-wrap:wrap}
|
| 57 |
+
.chips{display:flex;gap:4px}
|
| 58 |
+
.chip{background:var(--panel);border:1px solid var(--line);color:var(--muted);
|
| 59 |
+
padding:7px 12px;border-radius:7px;cursor:pointer;font-size:13px}
|
| 60 |
+
.chip.active{color:var(--text);border-color:var(--accent)}
|
| 61 |
+
.table-filter{background:var(--panel);border:1px solid var(--line);color:var(--text);
|
| 62 |
+
padding:8px 12px;border-radius:7px;outline:none;font-size:13px;width:140px}
|
| 63 |
+
.downloads{display:flex;gap:6px}
|
| 64 |
+
.dl{background:var(--panel2);border:1px solid var(--line);color:var(--text);
|
| 65 |
+
padding:8px 11px;border-radius:7px;cursor:pointer;font-size:13px}
|
| 66 |
+
.dl:hover{border-color:var(--accent)}
|
| 67 |
+
|
| 68 |
+
.pred-table{width:100%;border-collapse:collapse;font-size:14px}
|
| 69 |
+
.pred-table th{text-align:left;color:var(--muted);font-weight:600;font-size:12px;
|
| 70 |
+
text-transform:uppercase;letter-spacing:.04em;padding:8px 10px;border-bottom:1px solid var(--line)}
|
| 71 |
+
.pred-table td{padding:9px 10px;border-bottom:1px solid var(--panel2)}
|
| 72 |
+
.pred-table tr:hover td{background:var(--panel)}
|
| 73 |
+
.c-rank{width:38px;color:var(--muted)} .c-score{width:150px} .c-status{width:80px}
|
| 74 |
+
.tname{font-weight:600}
|
| 75 |
+
.tid a{font-size:12px;color:var(--muted)} .tid a:hover{color:var(--accent)}
|
| 76 |
+
.scorewrap{display:flex;align-items:center;gap:8px}
|
| 77 |
+
.bar{flex:1;height:7px;border-radius:5px;background:var(--panel2);overflow:hidden}
|
| 78 |
+
.bar>i{display:block;height:100%;background:linear-gradient(90deg,var(--accent),var(--accent2))}
|
| 79 |
+
.scoreval{font-variant-numeric:tabular-nums;color:var(--muted);font-size:12px;min-width:42px}
|
| 80 |
+
.badge{font-size:11px;padding:3px 9px;border-radius:20px;font-weight:700;text-transform:uppercase;letter-spacing:.03em}
|
| 81 |
+
.badge.known{color:var(--known);background:var(--known-bg)}
|
| 82 |
+
.badge.novel{color:var(--novel);background:var(--novel-bg)}
|
| 83 |
+
.no-rows{color:var(--muted);text-align:center;padding:24px}
|
| 84 |
+
|
| 85 |
+
/* entity-type chips */
|
| 86 |
+
.chip.drug,.chip.ind,.chip.prot{font-size:11px;padding:2px 8px;border-radius:20px;font-weight:700;
|
| 87 |
+
text-transform:uppercase;letter-spacing:.03em;border:0;cursor:default;vertical-align:middle}
|
| 88 |
+
.chip.drug{color:#7fb2ff;background:rgba(91,140,255,.16)}
|
| 89 |
+
.chip.ind{color:#e08bd0;background:rgba(224,139,208,.16)}
|
| 90 |
+
.chip.prot{color:#6fd3c0;background:rgba(63,178,178,.16)}
|
| 91 |
+
.tagline .chip{margin:0 1px}
|
| 92 |
+
#type-chip{margin-bottom:6px;display:inline-block}
|
| 93 |
+
.suggestions .s-left{display:flex;align-items:center;gap:8px;min-width:0}
|
| 94 |
+
.suggestions .sname{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
| 95 |
+
.examples button{display:inline-flex;align-items:center;gap:7px}
|
| 96 |
+
|
| 97 |
+
.site-footer{margin-top:50px;border-top:1px solid var(--line);padding:22px 0 40px;color:var(--muted);font-size:13px}
|
| 98 |
+
.site-footer .src{margin-top:6px;font-size:12px;opacity:.75}
|
test_app.py
DELETED
|
@@ -1,157 +0,0 @@
|
|
| 1 |
-
#!/usr/bin/env python3
|
| 2 |
-
"""
|
| 3 |
-
Quick test script to verify app.py data loading and functions work
|
| 4 |
-
Run this before launching the full Gradio app to catch errors early
|
| 5 |
-
"""
|
| 6 |
-
|
| 7 |
-
import sys
|
| 8 |
-
|
| 9 |
-
print("="*80)
|
| 10 |
-
print("TESTING APP.PY DATA LOADING AND FUNCTIONS")
|
| 11 |
-
print("="*80)
|
| 12 |
-
|
| 13 |
-
# Test 1: Import libraries
|
| 14 |
-
print("\n1. Testing library imports...")
|
| 15 |
-
try:
|
| 16 |
-
import pandas as pd
|
| 17 |
-
import numpy as np
|
| 18 |
-
import networkx as nx
|
| 19 |
-
print(" ✓ Core libraries imported")
|
| 20 |
-
except Exception as e:
|
| 21 |
-
print(f" ✗ Error importing libraries: {e}")
|
| 22 |
-
sys.exit(1)
|
| 23 |
-
|
| 24 |
-
try:
|
| 25 |
-
import gradio as gr
|
| 26 |
-
print(" ✓ Gradio imported")
|
| 27 |
-
except Exception as e:
|
| 28 |
-
print(f" ✗ Error importing Gradio: {e}")
|
| 29 |
-
print(" → Install with: uv pip install gradio")
|
| 30 |
-
sys.exit(1)
|
| 31 |
-
|
| 32 |
-
try:
|
| 33 |
-
import plotly.graph_objects as go
|
| 34 |
-
print(" ✓ Plotly imported")
|
| 35 |
-
except Exception as e:
|
| 36 |
-
print(f" ✗ Error importing Plotly: {e}")
|
| 37 |
-
print(" → Install with: uv pip install plotly")
|
| 38 |
-
sys.exit(1)
|
| 39 |
-
|
| 40 |
-
# Test 2: Load data files
|
| 41 |
-
print("\n2. Testing data file loading...")
|
| 42 |
-
|
| 43 |
-
required_files = {
|
| 44 |
-
'drug_nodes.csv': None,
|
| 45 |
-
'protein_nodes_with_embeddings.csv': None,
|
| 46 |
-
'drug_effects.csv': None,
|
| 47 |
-
'drugs_interactions.csv': None,
|
| 48 |
-
'graph_embeddings.npy': None,
|
| 49 |
-
'node_to_idx.npy': None
|
| 50 |
-
}
|
| 51 |
-
|
| 52 |
-
errors = []
|
| 53 |
-
|
| 54 |
-
try:
|
| 55 |
-
drug_nodes = pd.read_csv('drug_nodes.csv')
|
| 56 |
-
required_files['drug_nodes.csv'] = f"✓ {len(drug_nodes)} drugs"
|
| 57 |
-
print(f" ✓ drug_nodes.csv: {len(drug_nodes)} rows")
|
| 58 |
-
except Exception as e:
|
| 59 |
-
errors.append(f"drug_nodes.csv: {e}")
|
| 60 |
-
print(f" ✗ drug_nodes.csv: {e}")
|
| 61 |
-
|
| 62 |
-
try:
|
| 63 |
-
protein_nodes = pd.read_csv('protein_nodes_with_embeddings.csv')
|
| 64 |
-
required_files['protein_nodes_with_embeddings.csv'] = f"✓ {len(protein_nodes)} proteins"
|
| 65 |
-
print(f" ✓ protein_nodes_with_embeddings.csv: {len(protein_nodes)} rows")
|
| 66 |
-
except Exception as e:
|
| 67 |
-
errors.append(f"protein_nodes_with_embeddings.csv: {e}")
|
| 68 |
-
print(f" ✗ protein_nodes_with_embeddings.csv: {e}")
|
| 69 |
-
|
| 70 |
-
try:
|
| 71 |
-
drug_effects = pd.read_csv('drug_effects.csv')
|
| 72 |
-
required_files['drug_effects.csv'] = f"✓ {len(drug_effects)} effects"
|
| 73 |
-
print(f" ✓ drug_effects.csv: {len(drug_effects)} rows")
|
| 74 |
-
except Exception as e:
|
| 75 |
-
errors.append(f"drug_effects.csv: {e}")
|
| 76 |
-
print(f" ✗ drug_effects.csv: {e}")
|
| 77 |
-
|
| 78 |
-
try:
|
| 79 |
-
drugs_interactions = pd.read_csv('drugs_interactions.csv')
|
| 80 |
-
required_files['drugs_interactions.csv'] = f"✓ {len(drugs_interactions)} interactions"
|
| 81 |
-
print(f" ✓ drugs_interactions.csv: {len(drugs_interactions)} rows")
|
| 82 |
-
except Exception as e:
|
| 83 |
-
errors.append(f"drugs_interactions.csv: {e}")
|
| 84 |
-
print(f" ✗ drugs_interactions.csv: {e}")
|
| 85 |
-
|
| 86 |
-
try:
|
| 87 |
-
embeddings = np.load('graph_embeddings.npy')
|
| 88 |
-
required_files['graph_embeddings.npy'] = f"✓ {embeddings.shape}"
|
| 89 |
-
print(f" ✓ graph_embeddings.npy: shape {embeddings.shape}")
|
| 90 |
-
except Exception as e:
|
| 91 |
-
errors.append(f"graph_embeddings.npy: {e}")
|
| 92 |
-
print(f" ✗ graph_embeddings.npy: {e}")
|
| 93 |
-
|
| 94 |
-
try:
|
| 95 |
-
node_to_idx = np.load('node_to_idx.npy', allow_pickle=True).item()
|
| 96 |
-
required_files['node_to_idx.npy'] = f"✓ {len(node_to_idx)} nodes"
|
| 97 |
-
print(f" ✓ node_to_idx.npy: {len(node_to_idx)} nodes")
|
| 98 |
-
except Exception as e:
|
| 99 |
-
errors.append(f"node_to_idx.npy: {e}")
|
| 100 |
-
print(f" ✗ node_to_idx.npy: {e}")
|
| 101 |
-
|
| 102 |
-
# Test 3: Check data structure
|
| 103 |
-
if not errors:
|
| 104 |
-
print("\n3. Testing data structure...")
|
| 105 |
-
|
| 106 |
-
# Check drug_nodes columns
|
| 107 |
-
required_cols = ['drug_internal_id', 'drug_id', 'drug_name', 'smile']
|
| 108 |
-
missing_cols = [col for col in required_cols if col not in drug_nodes.columns]
|
| 109 |
-
if missing_cols:
|
| 110 |
-
print(f" ✗ drug_nodes missing columns: {missing_cols}")
|
| 111 |
-
errors.append(f"Missing columns in drug_nodes: {missing_cols}")
|
| 112 |
-
else:
|
| 113 |
-
print(f" ✓ drug_nodes has all required columns")
|
| 114 |
-
|
| 115 |
-
# Check protein_nodes columns
|
| 116 |
-
required_cols = ['protein_internal_id', 'protein_id', 'protein_name']
|
| 117 |
-
missing_cols = [col for col in required_cols if col not in protein_nodes.columns]
|
| 118 |
-
if missing_cols:
|
| 119 |
-
print(f" ✗ protein_nodes missing columns: {missing_cols}")
|
| 120 |
-
errors.append(f"Missing columns in protein_nodes: {missing_cols}")
|
| 121 |
-
else:
|
| 122 |
-
print(f" ✓ protein_nodes has all required columns")
|
| 123 |
-
|
| 124 |
-
# Test search function
|
| 125 |
-
print("\n4. Testing search function...")
|
| 126 |
-
try:
|
| 127 |
-
# Search for common drug
|
| 128 |
-
test_queries = ['Morphine', 'Aspirin', 'CHEMBL25']
|
| 129 |
-
for query in test_queries:
|
| 130 |
-
matches = drug_nodes[
|
| 131 |
-
drug_nodes['drug_name'].str.lower().str.contains(query.lower(), na=False) |
|
| 132 |
-
drug_nodes['drug_id'].str.lower().str.contains(query.lower(), na=False)
|
| 133 |
-
]
|
| 134 |
-
if len(matches) > 0:
|
| 135 |
-
print(f" ✓ Search '{query}': found {len(matches)} results")
|
| 136 |
-
else:
|
| 137 |
-
print(f" ⚠ Search '{query}': no results (might be OK)")
|
| 138 |
-
except Exception as e:
|
| 139 |
-
print(f" ✗ Search function error: {e}")
|
| 140 |
-
errors.append(f"Search error: {e}")
|
| 141 |
-
|
| 142 |
-
# Summary
|
| 143 |
-
print("\n" + "="*80)
|
| 144 |
-
if errors:
|
| 145 |
-
print("❌ TESTING FAILED")
|
| 146 |
-
print("\nErrors found:")
|
| 147 |
-
for i, error in enumerate(errors, 1):
|
| 148 |
-
print(f" {i}. {error}")
|
| 149 |
-
print("\nPlease fix these errors before running the app.")
|
| 150 |
-
sys.exit(1)
|
| 151 |
-
else:
|
| 152 |
-
print("✅ ALL TESTS PASSED!")
|
| 153 |
-
print("\nYour app should work correctly. Run it with:")
|
| 154 |
-
print(" ./run_app.sh")
|
| 155 |
-
print(" or")
|
| 156 |
-
print(" python app.py")
|
| 157 |
-
sys.exit(0)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
top_50_predicted_drug_effects.csv
DELETED
|
@@ -1,51 +0,0 @@
|
|
| 1 |
-
drug_chembl_id,drug_name,effect_id,effect_name,similarity
|
| 2 |
-
CHEMBL1257040,TRIFLUOPERAZINE HYDROCHLORIDE,D001714,Bipolar Disorder,0.545596
|
| 3 |
-
CHEMBL198362,RIVAROXABAN,D009203,Myocardial Infarction,0.5439486
|
| 4 |
-
CHEMBL435298,ESFLURBIPROFEN,D012216,Rheumatic Diseases,0.53732586
|
| 5 |
-
CHEMBL1201782,FOSAPREPITANT DIMEGLUMINE,D009325,Nausea,0.5282381
|
| 6 |
-
CHEMBL1709,SERTRALINE HYDROCHLORIDE,D016584,Panic Disorder,0.52576035
|
| 7 |
-
CHEMBL1200470,ESOMEPRAZOLE SODIUM,D015043,Zollinger-Ellison Syndrome,0.5249922
|
| 8 |
-
CHEMBL1951071,ARFORMOTEROL TARTRATE,D001986,Bronchial Spasm,0.51872176
|
| 9 |
-
CHEMBL1744447,ROSUVASTATIN CALCIUM,D050171,Dyslipidemias,0.5174923
|
| 10 |
-
CHEMBL2110372,RANITIDINE HYDROCHLORIDE,D004941,Esophagitis,0.5167754
|
| 11 |
-
CHEMBL1138,EZETIMIBE,D050171,Dyslipidemias,0.5112109
|
| 12 |
-
CHEMBL1201002,CARTEOLOL HYDROCHLORIDE,D009798,Ocular Hypertension,0.50021476
|
| 13 |
-
CHEMBL3707246,OZANIMOD HYDROCHLORIDE,D003424,Crohn Disease,0.49325937
|
| 14 |
-
CHEMBL4297088,CHLORHEXIDINE GLUCONATE,D003731,Dental Caries,0.49153596
|
| 15 |
-
CHEMBL4297216,FEDRATINIB HYDROCHLORIDE,D013920,"Thrombocythemia, Essential",0.49133992
|
| 16 |
-
CHEMBL1083385,CLOPIDOGREL BISULFATE,D011655,Pulmonary Embolism,0.49014294
|
| 17 |
-
CHEMBL1027,TIAGABINE,D012640,Seizures,0.48950252
|
| 18 |
-
CHEMBL2110372,RANITIDINE HYDROCHLORIDE,D005764,Gastroesophageal Reflux,0.48923716
|
| 19 |
-
CHEMBL572,NITROFURANTOIN,D011704,Pyelonephritis,0.4890899
|
| 20 |
-
CHEMBL503,LOVASTATIN,D050171,Dyslipidemias,0.48880434
|
| 21 |
-
CHEMBL1059,PREGABALIN,D001007,Anxiety,0.4883793
|
| 22 |
-
CHEMBL2105395,OSPEMIFENE,D016649,Primary Ovarian Insufficiency,0.48489913
|
| 23 |
-
CHEMBL2105662,LOMITAPIDE MESYLATE,D050171,Dyslipidemias,0.48404413
|
| 24 |
-
CHEMBL5314378,CASPOFUNGIN ACETATE,D016919,"Meningitis, Cryptococcal",0.48210338
|
| 25 |
-
CHEMBL2218894,FLUVASTATIN SODIUM,D050171,Dyslipidemias,0.48126566
|
| 26 |
-
CHEMBL3989844,DEXTROAMPHETAMINE SACCHARATE,D020181,"Sleep Apnea, Obstructive",0.48038968
|
| 27 |
-
CHEMBL501,AMPHETAMINE SULFATE,D020181,"Sleep Apnea, Obstructive",0.4802664
|
| 28 |
-
CHEMBL1650,CORTISONE ACETATE,D013167,"Spondylitis, Ankylosing",0.48004442
|
| 29 |
-
CHEMBL1213250,CEFTOLOZANE SULFATE,D011704,Pyelonephritis,0.47739014
|
| 30 |
-
CHEMBL1200402,AMLODIPINE BESYLATE,D050171,Dyslipidemias,0.47715414
|
| 31 |
-
CHEMBL1364144,METHYLPREDNISOLONE ACETATE,D013167,"Spondylitis, Ankylosing",0.4765048
|
| 32 |
-
CHEMBL406393,DEOXYCHOLIC ACID,D008105,"Liver Cirrhosis, Biliary",0.4760623
|
| 33 |
-
CHEMBL3544971,DEXTROAMPHETAMINE SULFATE,D020181,"Sleep Apnea, Obstructive",0.4735379
|
| 34 |
-
CHEMBL149972,PHENOBARBITAL SODIUM,D065768,Lennox Gastaut Syndrome,0.47247866
|
| 35 |
-
CHEMBL1650,CORTISONE ACETATE,D006255,"Rhinitis, Allergic, Seasonal",0.46704072
|
| 36 |
-
CHEMBL4650272,TRILACICLIB DIHYDROCHLORIDE,D018288,"Carcinoma, Small Cell",0.46695238
|
| 37 |
-
CHEMBL1201782,FOSAPREPITANT DIMEGLUMINE,D000855,Anorexia,0.46403712
|
| 38 |
-
CHEMBL3989923,PITAVASTATIN MAGNESIUM,D006938,Hyperlipoproteinemia Type II,0.46182984
|
| 39 |
-
CHEMBL1650,CORTISONE ACETATE,D009205,Myocarditis,0.4610492
|
| 40 |
-
CHEMBL1439,TAZOBACTAM SODIUM,D011704,Pyelonephritis,0.46001813
|
| 41 |
-
CHEMBL1441059,ALBUTEROL SULFATE,D008173,"Lung Diseases, Obstructive",0.45689774
|
| 42 |
-
CHEMBL650,METHYLPREDNISOLONE,D009879,"Ophthalmia, Sympathetic",0.45684493
|
| 43 |
-
CHEMBL1200804,DICLOFENAC POTASSIUM,D013166,Spondylitis,0.45582262
|
| 44 |
-
CHEMBL444633,RIFABUTIN,D001327,Autoimmune Diseases,0.45484185
|
| 45 |
-
CHEMBL5314378,CASPOFUNGIN ACETATE,D009091,Mucormycosis,0.45365286
|
| 46 |
-
CHEMBL137,METRONIDAZOLE,D012141,Respiratory Tract Infections,0.45224336
|
| 47 |
-
CHEMBL675,ALENDRONATE SODIUM,D001847,Bone Diseases,0.45178664
|
| 48 |
-
CHEMBL1269025,EDOXABAN,D054556,Venous Thromboembolism,0.4506775
|
| 49 |
-
CHEMBL1200865,LOTEPREDNOL ETABONATE,D006255,"Rhinitis, Allergic, Seasonal",0.44942963
|
| 50 |
-
CHEMBL1790041,RANITIDINE,D004381,Duodenal Ulcer,0.44910604
|
| 51 |
-
CHEMBL89598,VIGABATRIN,D012640,Seizures,0.44849676
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
top_50_predicted_drug_protein.csv
DELETED
|
@@ -1,51 +0,0 @@
|
|
| 1 |
-
drug_chembl_id,drug_name,protein_id,protein_name,similarity
|
| 2 |
-
CHEMBL3137320,TALAZOPARIB,CHEMBL2429709,Protein mono-ADP-ribosyltransferase PARP12,0.6001407
|
| 3 |
-
CHEMBL3137320,TALAZOPARIB,CHEMBL2429708,Protein mono-ADP-ribosyltransferase PARP10,0.5721854
|
| 4 |
-
CHEMBL1909072,PIPAMAZINE,CHEMBL1821,Muscarinic acetylcholine receptor M4,0.5399119
|
| 5 |
-
CHEMBL419,MAFENIDE,CHEMBL3912,Carbonic anhydrase 13,0.5392196
|
| 6 |
-
CHEMBL633,AMIODARONE,CHEMBL3371,5-hydroxytryptamine receptor 6,0.530897
|
| 7 |
-
CHEMBL11,IMIPRAMINE,CHEMBL223,Alpha-1D adrenergic receptor,0.5215963
|
| 8 |
-
CHEMBL17860,LOFEXIDINE,CHEMBL223,Alpha-1D adrenergic receptor,0.51608485
|
| 9 |
-
CHEMBL1421,DASATINIB ANHYDROUS,CHEMBL2250,Tyrosine-protein kinase Blk,0.512127
|
| 10 |
-
CHEMBL750,ZONISAMIDE,CHEMBL3510,Carbonic anhydrase 14,0.5120319
|
| 11 |
-
CHEMBL1567,SUNITINIB MALATE,CHEMBL2007,Platelet-derived growth factor receptor alpha,0.5054646
|
| 12 |
-
CHEMBL1173055,RUCAPARIB,CHEMBL2429709,Protein mono-ADP-ribosyltransferase PARP12,0.5037701
|
| 13 |
-
CHEMBL5315125,DUVELISIB MONOHYDRATE,CHEMBL3267,"Phosphatidylinositol 4,5-bisphosphate 3-kinase catalytic subunit gamma isoform",0.5015378
|
| 14 |
-
CHEMBL1963681,AVANAFIL,CHEMBL3977,"Cone cGMP-specific 3',5'-cyclic phosphodiesterase subunit alpha'",0.4979903
|
| 15 |
-
CHEMBL1621,PALIPERIDONE,CHEMBL3371,5-hydroxytryptamine receptor 6,0.49721804
|
| 16 |
-
CHEMBL762,OXYMETAZOLINE,CHEMBL217,D(2) dopamine receptor,0.4957183
|
| 17 |
-
CHEMBL1078178,MOMELOTINIB,CHEMBL5970,Mitogen-activated protein kinase kinase kinase 3,0.49483612
|
| 18 |
-
CHEMBL3301610,ABEMACICLIB,CHEMBL3529,Inhibitor of nuclear factor kappa-B kinase subunit epsilon,0.49270734
|
| 19 |
-
CHEMBL3233142,LUMATEPERONE TOSYLATE,CHEMBL1899,5-hydroxytryptamine receptor 3A,0.49170905
|
| 20 |
-
CHEMBL3301607,FILGOTINIB,CHEMBL1913,Platelet-derived growth factor receptor beta,0.48964554
|
| 21 |
-
CHEMBL11,IMIPRAMINE,CHEMBL287,Sigma non-opioid intracellular receptor 1,0.48921353
|
| 22 |
-
CHEMBL1535,HYDROXYCHLOROQUINE,CHEMBL245,Muscarinic acetylcholine receptor M3,0.48900294
|
| 23 |
-
CHEMBL27,PROPRANOLOL,CHEMBL234,D(3) dopamine receptor,0.4874745
|
| 24 |
-
CHEMBL4164059,PITOLISANT HYDROCHLORIDE,CHEMBL3371,5-hydroxytryptamine receptor 6,0.48707014
|
| 25 |
-
CHEMBL669,CYCLOBENZAPRINE,CHEMBL1821,Muscarinic acetylcholine receptor M4,0.48594135
|
| 26 |
-
CHEMBL978,METHACHOLINE,CHEMBL2035,Muscarinic acetylcholine receptor M5,0.48447487
|
| 27 |
-
CHEMBL487253,BENDAMUSTINE,CHEMBL3310,Histone deacetylase 11,0.48373866
|
| 28 |
-
CHEMBL86,METOCLOPRAMIDE,CHEMBL287,Sigma non-opioid intracellular receptor 1,0.48338604
|
| 29 |
-
CHEMBL644,TRIMIPRAMINE,CHEMBL223,Alpha-1D adrenergic receptor,0.48287874
|
| 30 |
-
CHEMBL808,ECONAZOLE,CHEMBL2035,Muscarinic acetylcholine receptor M5,0.4823854
|
| 31 |
-
CHEMBL621,TRAZODONE,CHEMBL2056,D(1A) dopamine receptor,0.4819331
|
| 32 |
-
CHEMBL1078178,MOMELOTINIB,CHEMBL3981,Serine/threonine-protein kinase 10,0.48185122
|
| 33 |
-
CHEMBL726,FLUPHENAZINE,CHEMBL2035,Muscarinic acetylcholine receptor M5,0.48140538
|
| 34 |
-
CHEMBL1421,DASATINIB ANHYDROUS,CHEMBL2007,Platelet-derived growth factor receptor alpha,0.48100707
|
| 35 |
-
CHEMBL1123,DICYCLOMINE,CHEMBL222,Sodium-dependent noradrenaline transporter,0.4806236
|
| 36 |
-
CHEMBL1834657,INFIGRATINIB PHOSPHATE,CHEMBL4722,Aurora kinase A,0.47917944
|
| 37 |
-
CHEMBL1852688,INFIGRATINIB,CHEMBL5627,Leukocyte tyrosine kinase receptor,0.47882342
|
| 38 |
-
CHEMBL671,THIOTEPA,CHEMBL1821,Muscarinic acetylcholine receptor M4,0.47861254
|
| 39 |
-
CHEMBL24778,SILODOSIN,CHEMBL2056,D(1A) dopamine receptor,0.47838083
|
| 40 |
-
CHEMBL3348923,TOVORAFENIB,CHEMBL2637,Mitogen-activated protein kinase 10,0.47791788
|
| 41 |
-
CHEMBL81,RALOXIFENE,CHEMBL2035,Muscarinic acetylcholine receptor M5,0.47773397
|
| 42 |
-
CHEMBL3301622,GILTERITINIB,CHEMBL3357,Interleukin-1 receptor-associated kinase 1,0.47708613
|
| 43 |
-
CHEMBL1714574,TERCONAZOLE,CHEMBL231,Histamine H1 receptor,0.47602153
|
| 44 |
-
CHEMBL644,TRIMIPRAMINE,CHEMBL1821,Muscarinic acetylcholine receptor M4,0.47474152
|
| 45 |
-
CHEMBL1628227,DOXEPIN,CHEMBL233,Mu-type opioid receptor,0.47406977
|
| 46 |
-
CHEMBL1633,KETOTIFEN FUMARATE,CHEMBL287,Sigma non-opioid intracellular receptor 1,0.47347492
|
| 47 |
-
CHEMBL2035187,PACRITINIB,CHEMBL3778,Interleukin-1 receptor-associated kinase 4,0.47341335
|
| 48 |
-
CHEMBL255863,NILOTINIB,CHEMBL3981,Serine/threonine-protein kinase 10,0.4726472
|
| 49 |
-
CHEMBL1614701,SELUMETINIB,CHEMBL3938,Serine/threonine-protein kinase 16,0.47264248
|
| 50 |
-
CHEMBL3545110,RIBOCICLIB,CHEMBL5261,Serine/threonine-protein kinase TAO1,0.47261065
|
| 51 |
-
CHEMBL17860,LOFEXIDINE,CHEMBL2056,D(1A) dopamine receptor,0.47247177
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|