Fredaaaaaa commited on
Commit
5d048cc
Β·
verified Β·
1 Parent(s): e29e5fe

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +144 -95
app.py CHANGED
@@ -1,46 +1,52 @@
1
  import gradio as gr
2
  import requests
3
- from rdkit import Chem
4
- from rdkit.Chem import Descriptors
5
- import pandas as pd
6
  from inference import DDIPredictor
7
- import torch
8
  import re
9
 
10
  # Initialize your trained model
11
  predictor = DDIPredictor(".")
12
 
13
  def fetch_pubchem_data(drug_name):
14
- """Fetch drug data from PubChem by name"""
15
  try:
16
  # First, search for the compound ID
17
  search_url = f"https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/name/{drug_name}/cids/JSON"
18
- search_response = requests.get(search_url)
19
 
20
  if search_response.status_code != 200:
21
  return None, f"Drug '{drug_name}' not found in PubChem"
22
 
23
  cid = search_response.json()['IdentifierList']['CID'][0]
24
 
25
- # Fetch compound data
26
- compound_url = f"https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/cid/{cid}/property/CanonicalSMILES,MolecularWeight,XLogP,TPSA/JSON"
27
- compound_response = requests.get(compound_url)
 
 
 
 
 
 
28
 
29
  if compound_response.status_code != 200:
30
- return None, "Failed to fetch compound data"
31
 
32
  data = compound_response.json()['PropertyTable']['Properties'][0]
 
33
 
34
- # Calculate additional properties from SMILES
35
- mol = Chem.MolFromSmiles(data['CanonicalSMILES'])
36
- if mol:
37
- data['RotatableBondCount'] = Descriptors.NumRotatableBonds(mol)
38
- data['HBondDonorCount'] = Descriptors.NumHDonors(mol)
39
- data['HBondAcceptorCount'] = Descriptors.NumHAcceptors(mol)
40
- data['Complexity'] = Descriptors.MolWt(mol) # Simplified complexity
41
 
42
  return data, None
43
 
 
 
44
  except Exception as e:
45
  return None, f"Error fetching data: {str(e)}"
46
 
@@ -49,64 +55,101 @@ def generate_interaction_description(drug1_data, drug2_data):
49
 
50
  descriptions = []
51
 
52
- # Based on molecular weight difference
53
- mw_diff = abs(drug1_data['MolecularWeight'] - drug2_data['MolecularWeight'])
 
 
 
54
  if mw_diff > 500:
55
- descriptions.append("Significant molecular size difference may affect metabolism")
 
 
 
 
 
 
 
56
 
57
- # Based on lipophilicity (XLogP)
58
- logp_diff = abs(drug1_data.get('XLogP', 0) - drug2_data.get('XLogP', 0))
59
  if logp_diff > 3:
60
- descriptions.append("Differing lipophilicity may influence distribution and clearance")
 
 
 
 
 
 
 
61
 
62
- # Based on TPSA (polar surface area)
63
- tpsa_diff = abs(drug1_data.get('TPSA', 0) - drug2_data.get('TPSA', 0))
64
  if tpsa_diff > 100:
65
- descriptions.append("Varying polar surface areas suggest different membrane permeability")
 
 
 
 
 
 
 
 
 
 
 
66
 
67
- # Based on hydrogen bonding
68
- hbond_total1 = drug1_data.get('HBondDonorCount', 0) + drug1_data.get('HBondAcceptorCount', 0)
69
- hbond_total2 = drug2_data.get('HBondDonorCount', 0) + drug2_data.get('HBondAcceptorCount', 0)
70
- if abs(hbond_total1 - hbond_total2) > 8:
71
- descriptions.append("Differing hydrogen bonding capacity may affect protein binding")
 
72
 
73
  # Default description if no specific features stand out
74
  if not descriptions:
75
- descriptions.append("Potential pharmacokinetic interaction requiring clinical evaluation")
76
 
77
- return " ".join(descriptions)
78
 
79
  def check_drugbank_interaction(drug1_name, drug2_name):
80
- """Placeholder function to check DrugBank interactions (you'd need API access)"""
81
- # This is a mock function - you'd need actual DrugBank API access
82
  drug1_clean = drug1_name.lower().strip()
83
  drug2_clean = drug2_name.lower().strip()
84
 
85
- # Mock known interactions for demonstration
86
  known_interactions = {
87
- ('warfarin', 'aspirin'): 'Severe: Increased bleeding risk',
88
- ('warfarin', 'ibuprofen'): 'Moderate: Increased bleeding risk',
89
- ('simvastatin', 'clarithromycin'): 'Severe: Increased risk of myopathy',
90
- ('digoxin', 'quinine'): 'Moderate: Increased digoxin levels',
 
 
 
 
 
 
91
  }
92
 
93
- # Check both orders
94
- interaction = known_interactions.get((drug1_clean, drug2_clean)) or known_interactions.get((drug2_clean, drug1_clean))
 
95
 
96
  if interaction:
97
  return interaction
98
  else:
99
- return "No known interaction in mock database"
100
 
101
  def predict_ddi(drug1_name, drug2_name):
102
  """Main prediction function"""
103
  try:
 
 
 
104
  # Fetch data for both drugs
105
  drug1_data, error1 = fetch_pubchem_data(drug1_name)
106
  drug2_data, error2 = fetch_pubchem_data(drug2_name)
107
 
108
- if error1 or error2:
109
- return f"Error: {error1 or error2}", "", "", "", ""
 
 
110
 
111
  # Generate interaction description
112
  interaction_description = generate_interaction_description(drug1_data, drug2_data)
@@ -119,35 +162,43 @@ def predict_ddi(drug1_name, drug2_name):
119
 
120
  # Prepare detailed output
121
  drug1_info = f"""
122
- **{drug1_name} Properties:**
123
- - SMILES: {drug1_data['CanonicalSMILES']}
124
- - Molecular Weight: {drug1_data['MolecularWeight']:.2f}
125
- - LogP: {drug1_data.get('XLogP', 'N/A')}
126
- - TPSA: {drug1_data.get('TPSA', 'N/A')}
127
- - H-Bond Donors: {drug1_data.get('HBondDonorCount', 'N/A')}
128
- - H-Bond Acceptors: {drug1_data.get('HBondAcceptorCount', 'N/A')}
 
 
 
129
  """
130
 
131
  drug2_info = f"""
132
- **{drug2_name} Properties:**
133
- - SMILES: {drug2_data['CanonicalSMILES']}
134
- - Molecular Weight: {drug2_data['MolecularWeight']:.2f}
135
- - LogP: {drug2_data.get('XLogP', 'N/A')}
136
- - TPSA: {drug2_data.get('TPSA', 'N/A')}
137
- - H-Bond Donors: {drug2_data.get('HBondDonorCount', 'N/A')}
138
- - H-Bond Acceptors: {drug2_data.get('HBondAcceptorCount', 'N/A')}
 
 
 
139
  """
140
 
141
  prediction_output = f"""
 
 
142
  **Generated Interaction Description:**
143
- {interaction_description}
144
 
145
- **AI Prediction:**
146
- - Severity: **{result['prediction']}**
147
- - Confidence: {result['confidence']:.2%}
148
 
149
- **Probabilities:**
150
- {', '.join([f'{k}: {v:.2%}' for k, v in result['probabilities'].items()])}
151
  """
152
 
153
  return prediction_output, drug1_info, drug2_info, drugbank_result, interaction_description
@@ -158,49 +209,47 @@ def predict_ddi(drug1_name, drug2_name):
158
  # Create Gradio interface
159
  with gr.Blocks(title="Drug Interaction Severity Predictor", theme=gr.themes.Soft()) as demo:
160
  gr.Markdown("# πŸ§ͺ Drug Interaction Severity Predictor")
161
- gr.Markdown("Predict potential drug-drug interaction severity using molecular properties and AI")
162
 
163
  with gr.Row():
164
- with gr.Column():
 
165
  drug1 = gr.Textbox(label="First Drug Name", placeholder="e.g., Warfarin, Aspirin, Simvastatin...")
166
- drug2 = gr.Textbox(label="Second Drug Name", placeholder="e.g., Ibuprofen, Clarithromycin...")
167
- predict_btn = gr.Button("Predict Interaction", variant="primary")
 
 
 
 
 
 
 
 
 
 
 
 
168
 
169
  with gr.Row():
170
- with gr.Column():
171
  gr.Markdown("## πŸ“Š Prediction Results")
172
  prediction_output = gr.Markdown(label="AI Prediction")
173
 
 
 
 
 
 
174
  with gr.Column():
175
- gr.Markdown("## πŸ” Drug Properties")
176
- with gr.Tab("Drug 1"):
177
  drug1_info = gr.Markdown()
178
- with gr.Tab("Drug 2"):
179
  drug2_info = gr.Markdown()
180
 
181
  with gr.Row():
182
- with gr.Column():
183
- gr.Markdown("## πŸ₯ DrugBank Comparison")
184
- drugbank_result = gr.Textbox(label="Known Interaction (Mock Data)", interactive=False)
185
-
186
- with gr.Column():
187
- gr.Markdown("## πŸ“ Generated Description")
188
- interaction_description = gr.Textbox(label="AI-Generated Interaction Description", interactive=False)
189
-
190
- # Examples
191
- gr.Markdown("### πŸ’‘ Example Drug Pairs")
192
- gr.Examples(
193
- examples=[
194
- ["Warfarin", "Aspirin"],
195
- ["Simvastatin", "Clarithromycin"],
196
- ["Digoxin", "Quinine"],
197
- ["Metformin", "Ibuprofen"]
198
- ],
199
- inputs=[drug1, drug2],
200
- outputs=[prediction_output, drug1_info, drug2_info, drugbank_result, interaction_description],
201
- fn=predict_ddi,
202
- cache_examples=True
203
- )
204
 
205
  predict_btn.click(
206
  fn=predict_ddi,
 
1
  import gradio as gr
2
  import requests
3
+ import json
 
 
4
  from inference import DDIPredictor
 
5
  import re
6
 
7
  # Initialize your trained model
8
  predictor = DDIPredictor(".")
9
 
10
  def fetch_pubchem_data(drug_name):
11
+ """Fetch comprehensive drug data from PubChem by name"""
12
  try:
13
  # First, search for the compound ID
14
  search_url = f"https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/name/{drug_name}/cids/JSON"
15
+ search_response = requests.get(search_url, timeout=10)
16
 
17
  if search_response.status_code != 200:
18
  return None, f"Drug '{drug_name}' not found in PubChem"
19
 
20
  cid = search_response.json()['IdentifierList']['CID'][0]
21
 
22
+ # Fetch comprehensive compound data
23
+ properties = [
24
+ 'CanonicalSMILES', 'MolecularWeight', 'XLogP', 'TPSA',
25
+ 'RotatableBondCount', 'HBondDonorCount', 'HBondAcceptorCount',
26
+ 'Complexity', 'Charge', 'ExactMass'
27
+ ]
28
+
29
+ compound_url = f"https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/cid/{cid}/property/{','.join(properties)}/JSON"
30
+ compound_response = requests.get(compound_url, timeout=10)
31
 
32
  if compound_response.status_code != 200:
33
+ return None, "Failed to fetch compound properties"
34
 
35
  data = compound_response.json()['PropertyTable']['Properties'][0]
36
+ data['CID'] = cid
37
 
38
+ # Get IUPAC name for better identification
39
+ iupac_url = f"https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/cid/{cid}/property/IUPACName/JSON"
40
+ iupac_response = requests.get(iupac_url, timeout=10)
41
+ if iupac_response.status_code == 200:
42
+ data['IUPACName'] = iupac_response.json()['PropertyTable']['Properties'][0]['IUPACName']
43
+ else:
44
+ data['IUPACName'] = drug_name
45
 
46
  return data, None
47
 
48
+ except requests.exceptions.Timeout:
49
+ return None, "PubChem API timeout - please try again"
50
  except Exception as e:
51
  return None, f"Error fetching data: {str(e)}"
52
 
 
55
 
56
  descriptions = []
57
 
58
+ # Molecular weight analysis
59
+ mw1 = drug1_data.get('MolecularWeight', 0)
60
+ mw2 = drug2_data.get('MolecularWeight', 0)
61
+ mw_diff = abs(mw1 - mw2)
62
+
63
  if mw_diff > 500:
64
+ descriptions.append("Significant molecular size difference may affect metabolic pathways")
65
+ elif mw_diff > 200:
66
+ descriptions.append("Moderate molecular size difference could influence distribution")
67
+
68
+ # Lipophilicity analysis (XLogP)
69
+ logp1 = drug1_data.get('XLogP', 0)
70
+ logp2 = drug2_data.get('XLogP', 0)
71
+ logp_diff = abs(logp1 - logp2)
72
 
 
 
73
  if logp_diff > 3:
74
+ descriptions.append("Differing lipophilicity may affect membrane permeability and clearance rates")
75
+ elif logp_diff > 1.5:
76
+ descriptions.append("Variation in lipophilicity could influence tissue distribution")
77
+
78
+ # Polar surface area analysis
79
+ tpsa1 = drug1_data.get('TPSA', 0)
80
+ tpsa2 = drug2_data.get('TPSA', 0)
81
+ tpsa_diff = abs(tpsa1 - tpsa2)
82
 
 
 
83
  if tpsa_diff > 100:
84
+ descriptions.append("Significant difference in polar surface area suggests varying bioavailability")
85
+ elif tpsa_diff > 50:
86
+ descriptions.append("Moderate difference in polar surface area may affect absorption")
87
+
88
+ # Hydrogen bonding analysis
89
+ h_donor1 = drug1_data.get('HBondDonorCount', 0)
90
+ h_donor2 = drug2_data.get('HBondDonorCount', 0)
91
+ h_acceptor1 = drug1_data.get('HBondAcceptorCount', 0)
92
+ h_acceptor2 = drug2_data.get('HBondAcceptorCount', 0)
93
+
94
+ if abs(h_donor1 - h_donor2) > 3 or abs(h_acceptor1 - h_acceptor2) > 5:
95
+ descriptions.append("Differing hydrogen bonding capacity may affect protein binding and metabolism")
96
 
97
+ # Rotatable bonds analysis
98
+ rotatable1 = drug1_data.get('RotatableBondCount', 0)
99
+ rotatable2 = drug2_data.get('RotatableBondCount', 0)
100
+
101
+ if abs(rotatable1 - rotatable2) > 8:
102
+ descriptions.append("Significant difference in molecular flexibility may influence receptor binding")
103
 
104
  # Default description if no specific features stand out
105
  if not descriptions:
106
+ descriptions.append("Potential pharmacokinetic interaction based on molecular properties - clinical evaluation recommended")
107
 
108
+ return ". ".join(descriptions) + "."
109
 
110
  def check_drugbank_interaction(drug1_name, drug2_name):
111
+ """Mock function to simulate DrugBank interaction check"""
112
+ # Convert to lowercase for case-insensitive matching
113
  drug1_clean = drug1_name.lower().strip()
114
  drug2_clean = drug2_name.lower().strip()
115
 
116
+ # Expanded mock database of known interactions
117
  known_interactions = {
118
+ ('warfarin', 'aspirin'): 'Severe: Increased risk of bleeding and hemorrhage',
119
+ ('warfarin', 'ibuprofen'): 'Moderate: Increased risk of gastrointestinal bleeding',
120
+ ('warfarin', 'simvastatin'): 'Moderate: Increased anticoagulant effect',
121
+ ('simvastatin', 'clarithromycin'): 'Severe: Increased risk of myopathy and rhabdomyolysis',
122
+ ('simvastatin', 'itraconazole'): 'Severe: Increased statin levels and toxicity risk',
123
+ ('digoxin', 'quinine'): 'Moderate: Increased digoxin levels, risk of toxicity',
124
+ ('digoxin', 'verapamil'): 'Moderate: Increased digoxin concentrations',
125
+ ('lisinopril', 'ibuprofen'): 'Moderate: Reduced antihypertensive effect',
126
+ ('metformin', 'contrast'): 'Severe: Risk of lactic acidosis with contrast media',
127
+ ('phenytoin', 'warfarin'): 'Moderate: Altered anticoagulant effect',
128
  }
129
 
130
+ # Check both orders of drug names
131
+ interaction = (known_interactions.get((drug1_clean, drug2_clean)) or
132
+ known_interactions.get((drug2_clean, drug1_clean)))
133
 
134
  if interaction:
135
  return interaction
136
  else:
137
+ return "No known severe interaction in database (mock data)"
138
 
139
  def predict_ddi(drug1_name, drug2_name):
140
  """Main prediction function"""
141
  try:
142
+ if not drug1_name or not drug2_name:
143
+ return "Please enter both drug names", "", "", "", ""
144
+
145
  # Fetch data for both drugs
146
  drug1_data, error1 = fetch_pubchem_data(drug1_name)
147
  drug2_data, error2 = fetch_pubchem_data(drug2_name)
148
 
149
+ if error1:
150
+ return f"Error with {drug1_name}: {error1}", "", "", "", ""
151
+ if error2:
152
+ return f"Error with {drug2_name}: {error2}", "", "", "", ""
153
 
154
  # Generate interaction description
155
  interaction_description = generate_interaction_description(drug1_data, drug2_data)
 
162
 
163
  # Prepare detailed output
164
  drug1_info = f"""
165
+ **{drug1_name}** (PubChem CID: {drug1_data.get('CID', 'N/A')})
166
+ - **IUPAC Name:** {drug1_data.get('IUPACName', 'N/A')}
167
+ - **SMILES:** {drug1_data.get('CanonicalSMILES', 'N/A')}
168
+ - **Molecular Weight:** {drug1_data.get('MolecularWeight', 'N/A')} g/mol
169
+ - **LogP (XLogP):** {drug1_data.get('XLogP', 'N/A')}
170
+ - **TPSA:** {drug1_data.get('TPSA', 'N/A')} Γ…Β²
171
+ - **H-Bond Donors:** {drug1_data.get('HBondDonorCount', 'N/A')}
172
+ - **H-Bond Acceptors:** {drug1_data.get('HBondAcceptorCount', 'N/A')}
173
+ - **Rotatable Bonds:** {drug1_data.get('RotatableBondCount', 'N/A')}
174
+ - **Complexity:** {drug1_data.get('Complexity', 'N/A')}
175
  """
176
 
177
  drug2_info = f"""
178
+ **{drug2_name}** (PubChem CID: {drug2_data.get('CID', 'N/A')})
179
+ - **IUPAC Name:** {drug2_data.get('IUPACName', 'N/A')}
180
+ - **SMILES:** {drug2_data.get('CanonicalSMILES', 'N/A')}
181
+ - **Molecular Weight:** {drug2_data.get('MolecularWeight', 'N/A')} g/mol
182
+ - **LogP (XLogP):** {drug2_data.get('XLogP', 'N/A')}
183
+ - **TPSA:** {drug2_data.get('TPSA', 'N/A')} Γ…Β²
184
+ - **H-Bond Donors:** {drug2_data.get('HBondDonorCount', 'N/A')}
185
+ - **H-Bond Acceptors:** {drug2_data.get('HBondAcceptorCount', 'N/A')}
186
+ - **Rotatable Bonds:** {drug2_data.get('RotatableBondCount', 'N/A')}
187
+ - **Complexity:** {drug2_data.get('Complexity', 'N/A')}
188
  """
189
 
190
  prediction_output = f"""
191
+ ## πŸ” AI Prediction Results
192
+
193
  **Generated Interaction Description:**
194
+ *"{interaction_description}"*
195
 
196
+ **Prediction:**
197
+ - **Severity:** **{result['prediction']}**
198
+ - **Confidence:** {result['confidence']:.1%}
199
 
200
+ **Probability Distribution:**
201
+ {', '.join([f'{k}: {v:.1%}' for k, v in result['probabilities'].items()])}
202
  """
203
 
204
  return prediction_output, drug1_info, drug2_info, drugbank_result, interaction_description
 
209
  # Create Gradio interface
210
  with gr.Blocks(title="Drug Interaction Severity Predictor", theme=gr.themes.Soft()) as demo:
211
  gr.Markdown("# πŸ§ͺ Drug Interaction Severity Predictor")
212
+ gr.Markdown("Predict potential drug-drug interaction severity using molecular properties from PubChem and AI")
213
 
214
  with gr.Row():
215
+ with gr.Column(scale=1):
216
+ gr.Markdown("## πŸ’Š Input Drug Names")
217
  drug1 = gr.Textbox(label="First Drug Name", placeholder="e.g., Warfarin, Aspirin, Simvastatin...")
218
+ drug2 = gr.Textbox(label="Second Drug Name", placeholder="e.g., Ibuprofen, Clarithromycin, Digoxin...")
219
+ predict_btn = gr.Button("πŸ”¬ Predict Interaction", variant="primary", size="lg")
220
+
221
+ gr.Markdown("### πŸ’‘ Example Pairs")
222
+ gr.Examples(
223
+ examples=[
224
+ ["Warfarin", "Aspirin"],
225
+ ["Simvastatin", "Clarithromycin"],
226
+ ["Digoxin", "Quinine"],
227
+ ["Lisinopril", "Ibuprofen"]
228
+ ],
229
+ inputs=[drug1, drug2],
230
+ label="Try these examples:"
231
+ )
232
 
233
  with gr.Row():
234
+ with gr.Column(scale=2):
235
  gr.Markdown("## πŸ“Š Prediction Results")
236
  prediction_output = gr.Markdown(label="AI Prediction")
237
 
238
+ with gr.Column(scale=1):
239
+ gr.Markdown("## πŸ₯ DrugBank Check")
240
+ drugbank_result = gr.Textbox(label="Known Interaction (Mock Data)", interactive=False)
241
+
242
+ with gr.Row():
243
  with gr.Column():
244
+ gr.Markdown("## πŸ” Molecular Properties")
245
+ with gr.Tab("Drug 1 Properties"):
246
  drug1_info = gr.Markdown()
247
+ with gr.Tab("Drug 2 Properties"):
248
  drug2_info = gr.Markdown()
249
 
250
  with gr.Row():
251
+ gr.Markdown("## πŸ“ Generated Description")
252
+ interaction_description = gr.Textbox(label="AI-Generated Interaction Description", interactive=False, lines=3)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
253
 
254
  predict_btn.click(
255
  fn=predict_ddi,