mgbam commited on
Commit
88daccb
·
verified ·
1 Parent(s): 4f9d22e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +162 -268
app.py CHANGED
@@ -1,299 +1,193 @@
1
  import streamlit as st
2
- from smolagents import CodeAgent, DuckDuckGoSearchTool, HfApiModel
3
  from rdkit import Chem
4
- from rdkit.Chem import Draw, AllChem, Descriptors, Lipinski
5
  from rdkit.Chem.Draw import rdMolDraw2D
6
- from rdkit.Chem import PandasTools
7
- from fpdf import FPDF
8
- import tempfile
9
- import time
10
- import requests
11
- import xml.etree.ElementTree as ET
12
- import json
13
  import pandas as pd
14
  import numpy as np
 
15
  import matplotlib.pyplot as plt
16
- import seaborn as sns
17
- import py3Dmol
18
- from stmol import showmol
19
- from typing import Optional, Dict, List, Any
20
- from streamlit_modal import Modal
21
  import plotly.express as px
22
  from PIL import Image
23
  from io import BytesIO
24
- import pubchempy as pcp
25
- import biopython as bp
26
- from deepchem.models import Tox21TensorGraph
27
  from mordred import Calculator, descriptors
 
 
 
 
 
 
 
 
 
 
 
 
28
 
29
- # Enhanced API Endpoints with Authentication
30
- API_ENDPOINTS = {
31
- "clinical_trials": {
 
32
  "url": "https://clinicaltrials.gov/api/v2/studies",
33
  "params": {"format": "json"}
34
  },
35
- "pubchem": "https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/name/{}/JSON",
36
- "drugbank": {
37
- "url": "https://go.drugbank.com/releases/latest/",
38
- "headers": {"Authorization": f"Bearer {st.secrets['DRUGBANK_API_KEY']}"}
39
- },
40
- "uniprot": "https://rest.uniprot.org/uniprotkb/search?query={}&format=json",
41
  "chembl": "https://www.ebi.ac.uk/chembl/api/data/molecule?pref_name__iexact={}&format=json",
42
- "protein_data_bank": "https://data.rcsb.org/rest/v1/core/entry/{}",
43
- "clinicaltrials_ai": "https://api.clinicaltrials.ai/v1/analysis",
44
- "openadr": "https://api.openadr.org/v2/reactions"
45
  }
46
 
47
- # Initialize AI Agents with Domain Specialization
48
- content_agent = CodeAgent(
49
- tools=[DuckDuckGoSearchTool()],
50
- model=HfApiModel(),
51
- system_prompt="You are a pharmaceutical research expert with 20 years of experience in drug discovery and development."
52
- )
53
-
54
- tox21_model = Tox21TensorGraph.load_from_dir('tox21_model')
55
  mordred_calculator = Calculator(descriptors, ignore_3D=True)
56
 
57
- # --- Advanced Visualization Functions ---
58
  def render_3d_molecule(smiles: str):
59
- """Interactive 3D molecular visualization"""
 
 
 
 
 
 
 
 
60
  mol = Chem.MolFromSmiles(smiles)
61
  if mol:
62
- mol = Chem.AddHs(mol)
63
- AllChem.EmbedMolecule(mol)
64
- AllChem.MMFFOptimizeMolecule(mol)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
 
66
- viewer = py3Dmol.view(width=400, height=300)
67
- viewer.addModel(Chem.MolToMolBlock(mol), 'mol')
68
- viewer.setStyle({'stick': {}, 'sphere': {'radius': 0.3}})
69
- viewer.zoomTo()
70
- showmol(viewer, height=300, width=400)
71
-
72
- def plot_chemical_space(descriptors_df):
73
- """3D PCA visualization of chemical space"""
74
- from sklearn.decomposition import PCA
75
- pca = PCA(n_components=3)
76
- components = pca.fit_transform(descriptors_df.dropna(axis=1))
77
- fig = px.scatter_3d(
78
- x=components[:,0], y=components[:,1], z=components[:,2],
79
- color=descriptors_df['compound'],
80
- labels={'color': 'Compound'},
81
- title="3D Chemical Space Analysis"
82
- )
83
- st.plotly_chart(fig)
84
-
85
- # --- Enhanced API Handlers with Cache ---
86
- @st.cache_data(ttl=3600)
87
- def _query_api_enhanced(endpoint_config: dict, params: Optional[Dict] = None) -> Optional[Dict]:
88
- """Advanced API handler with retry logic and rate limiting"""
89
- headers = endpoint_config.get('headers', {})
90
- try:
91
- response = requests.get(
92
- endpoint_config['url'],
93
- params={**endpoint_config.get('params', {}), **params} if params else endpoint_config.get('params', {}),
94
- headers=headers,
95
- timeout=20
96
- )
97
- response.raise_for_status()
98
- return response.json()
99
- except requests.exceptions.HTTPError as e:
100
- st.error(f"API Error ({response.status_code}): {e.response.text}")
101
- return None
102
- except requests.exceptions.RequestException as e:
103
- st.error(f"Network Error: {str(e)}")
104
- return None
105
-
106
- # --- Quantum Chemistry Calculations ---
107
- def calculate_docking_score(smiles: str, target_pdb: str):
108
- """Simplified molecular docking simulation"""
109
- from rdkit.Chem import AllChem
110
- from scipy.spatial.distance import cdist
111
-
112
- # Placeholder for actual docking implementation
113
- ligand = Chem.MolFromSmiles(smiles)
114
- protein = Chem.MolFromPDBFile(target_pdb)
115
-
116
- if ligand and protein:
117
- AllChem.EmbedMolecule(ligand)
118
- ligand_pos = ligand.GetConformer().GetPositions()
119
- protein_pos = protein.GetConformer().GetPositions()
120
-
121
- # Calculate minimal distance between ligand and protein atoms
122
- distances = cdist(ligand_pos, protein_pos)
123
- return np.min(distances)
124
- return None
125
-
126
- # --- Streamlit App Configuration ---
127
- st.set_page_config(page_title="PharmaAI Research Suite", layout="wide", page_icon="🧪")
128
- st.title("🧪 PharmaAI Research Suite")
129
- st.markdown("""
130
- **Next-Gen Drug Discovery Platform**
131
- *Integrating AI, Quantum Chemistry, and Multi-Omics Data*
132
- """)
133
-
134
- # --- Main Tabs ---
135
- tabs = st.tabs([
136
- "🚀 Drug Discovery AI",
137
- "🌐 Clinical Intelligence",
138
- "🧬 Molecular Studio",
139
- "📈 ADMET Prediction",
140
- "🌍 Global Regulatory"
141
- ])
142
-
143
- # --- Tab 1: Drug Discovery AI ---
144
- with tabs[0]:
145
- col1, col2 = st.columns([2, 3])
146
- with col1:
147
- st.subheader("AI-Driven Design")
148
- target_input = st.text_input("Target Protein or Disease:", placeholder="Enter PDB ID or disease name")
149
- design_strategy = st.selectbox("Design Strategy:", [
150
- "De Novo Generation",
151
- "Scaffold Hopping",
152
- "Active Learning Optimization"
153
- ])
154
 
155
- if st.button("Generate Novel Compounds"):
156
- with st.spinner("Running generative AI models..."):
157
- prompt = f"""
158
- Design 5 novel drug candidates targeting {target_input} using {design_strategy} approach.
159
- Include detailed rationale covering:
160
- - Target binding mode prediction
161
- - SAR analysis of generated compounds
162
- - Synthetic accessibility scores
163
- - Patent landscape considerations
164
- """
165
- results = content_agent.run(prompt)
166
- st.markdown(results)
167
-
168
- with col2:
169
- st.subheader("Virtual Screening Results")
170
- if 'generated_smiles' in st.session_state:
171
- render_3d_molecule(st.session_state.generated_smiles[0])
172
- st.plotly_chart(plot_chemical_space(st.session_state.descriptors))
173
-
174
- # --- Tab 2: Clinical Intelligence ---
175
- with tabs[1]:
176
- st.subheader("AI-Powered Trial Design")
177
- trial_design_type = st.radio("Trial Type:", ["Adaptive", "Basket", "Umbrella", "Platform"])
178
-
179
- col1, col2 = st.columns(2)
180
- with col1:
181
- nct_id = st.text_input("NCT Number for Analysis:")
182
- if st.button("Run Trial Simulation"):
183
- with st.spinner("Analyzing trial parameters..."):
184
- simulation_results = content_agent.run(
185
- f"Simulate clinical outcomes for {nct_id} using Bayesian adaptive design methods"
186
- )
187
- st.markdown(simulation_results)
188
-
189
- with col2:
190
- st.subheader("Real-World Evidence")
191
- ae_data = _query_api_enhanced(API_ENDPOINTS['openadr'], {"drug": target_input})
192
- if ae_data:
193
- fig = px.sunburst(ae_data, path=['category', 'reaction'], values='count')
194
- st.plotly_chart(fig)
195
-
196
- # --- Tab 3: Molecular Studio ---
197
- with tabs[2]:
198
- st.subheader("Advanced Molecular Analysis")
199
- compound_input = st.text_input("Enter Compound Identifier:",
200
- placeholder="SMILES, IUPAC Name, or InChIKey")
201
-
202
- if compound_input:
203
- with st.spinner("Computing molecular properties..."):
204
  try:
205
- mol = pcp.get_compounds(compound_input, 'name')[0]
206
- st.session_state.molecule = mol
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
207
 
208
- col1, col2, col3 = st.columns([2, 2, 2])
209
- with col1:
210
- st.subheader("3D Structure")
211
- render_3d_molecule(mol.canonical_smiles)
212
-
213
- with col2:
214
- st.subheader("Quantum Properties")
215
- mordred_df = mordred_calculator.pandas([mol.to_rdkit()])
216
- st.dataframe(mordred_df.describe())
217
-
218
- with col3:
219
- st.subheader("Binding Affinity")
220
- docking_score = calculate_docking_score(mol.canonical_smiles, "1abc.pdb")
221
- st.metric("Predicted Docking Score", f"{docking_score:.2f} Å")
222
-
223
  except Exception as e:
224
- st.error(f"Molecular analysis failed: {str(e)}")
225
 
226
- # --- Tab 4: ADMET Prediction ---
227
- with tabs[3]:
228
- st.subheader("AI-Powered ADMET Prediction")
229
- if 'molecule' in st.session_state:
230
- tox21_preds = tox21_model.predict([st.session_state.molecule.to_rdkit()])
231
- st.write("Tox21 Predictions:", tox21_preds)
232
 
233
- admet_plot = px.parallel_coordinates(
234
- pd.DataFrame(tox21_preds),
235
- color="NR-AR",
236
- title="ADMET Profile Radar Chart"
237
- )
238
- st.plotly_chart(admet_plot)
239
-
240
- # --- Tab 5: Global Regulatory ---
241
- with tabs[4]:
242
- st.subheader("Real-Time Regulatory Monitoring")
243
- reg_countries = st.multiselect("Select Jurisdictions:",
244
- ["FDA", "EMA", "PMDA", "NMPA", "Health Canada"])
245
-
246
- if st.button("Run Regulatory Analysis"):
247
- with st.spinner("Aggregating global regulatory data..."):
248
- reg_data = []
249
- for agency in reg_countries:
250
- response = content_agent.run(
251
- f"Generate detailed regulatory intelligence report for {target_input} in {agency}"
252
- )
253
- reg_data.append(response)
254
-
255
- st.subheader("Comparative Regulatory Analysis")
256
- st.altair_chart(plot_regulatory_timeline(reg_data))
257
-
258
- report = generate_pdf_report(reg_data)
259
- st.download_button("Download Full Report", report, file_name="regulatory_analysis.pdf")
260
-
261
- # --- Collaborative Features ---
262
- with st.sidebar:
263
- st.header("Collaboration Tools")
264
- project_id = st.text_input("Project ID:")
265
- if st.button("Sync with Electronic Lab Notebook"):
266
- st.success("Connected to Benchling API")
267
 
268
- st.subheader("Live Discussion")
269
- comment = st.text_area("Add research note:")
270
- if st.button("Post to Team"):
271
- st.session_state.research_notes.append(comment)
272
-
273
- # --- System Status ---
274
- st.sidebar.markdown("## System Status")
275
- st.sidebar.progress(0.8, text="AI Model Capacity")
276
- st.sidebar.metric("Active Users", "142", "+8 today")
277
-
278
- # --- Advanced Features Modal ---
279
- advanced_modal = Modal("Quantum Computing Interface", key="qc_modal")
280
- if st.sidebar.button("Quantum Computing"):
281
- advanced_modal.open()
282
-
283
- if advanced_modal.is_open():
284
- with advanced_modal.container():
285
- st.write("Quantum Chemistry Calculations")
286
- qc_input = st.text_input("Enter SMILES for QC simulation:")
287
- if st.button("Run Quantum Simulation"):
288
- with st.spinner("Running on quantum processor..."):
289
- time.sleep(2)
290
- st.success("Simulation complete! Energy: -154.82 Hartrees")
291
 
292
- # --- Theme Configuration ---
293
- st.markdown("""
294
- <style>
295
- .stApp { background-color: #f5f5f5 }
296
- .stTextInput input { background-color: #f0f2f6 }
297
- .css-1d391kg { padding: 20px; border-radius: 10px; }
298
- </style>
299
- """, unsafe_allow_html=True)
 
1
  import streamlit as st
2
+ import py3Dmol
3
  from rdkit import Chem
4
+ from rdkit.Chem import AllChem, Draw, Descriptors, PandasTools
5
  from rdkit.Chem.Draw import rdMolDraw2D
 
 
 
 
 
 
 
6
  import pandas as pd
7
  import numpy as np
8
+ import requests
9
  import matplotlib.pyplot as plt
 
 
 
 
 
10
  import plotly.express as px
11
  from PIL import Image
12
  from io import BytesIO
13
+ from fpdf import FPDF
14
+ from streamlit.components.v1 import html
 
15
  from mordred import Calculator, descriptors
16
+ import pubchempy as pcp
17
+ from typing import Optional, Dict, List, Any
18
+
19
+ # --- Configuration ---
20
+ st.set_page_config(page_title="PharmaAI Suite", layout="wide", page_icon="🧬")
21
+ st.markdown("""
22
+ <style>
23
+ .stApp { background-color: #f0f2f6 }
24
+ .css-1d391kg { padding: 20px; border-radius: 10px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
25
+ h2 { color: #2c3e50; }
26
+ </style>
27
+ """, unsafe_allow_html=True)
28
 
29
+ # --- API Endpoints ---
30
+ API_CONFIG = {
31
+ "pubchem": "https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/name/{}/JSON",
32
+ "clinicaltrials": {
33
  "url": "https://clinicaltrials.gov/api/v2/studies",
34
  "params": {"format": "json"}
35
  },
 
 
 
 
 
 
36
  "chembl": "https://www.ebi.ac.uk/chembl/api/data/molecule?pref_name__iexact={}&format=json",
37
+ "uniprot": "https://rest.uniprot.org/uniprotkb/search?query={}&format=json"
 
 
38
  }
39
 
40
+ # --- Advanced Calculators ---
 
 
 
 
 
 
 
41
  mordred_calculator = Calculator(descriptors, ignore_3D=True)
42
 
43
+ # --- Core Functions ---
44
  def render_3d_molecule(smiles: str):
45
+ """Interactive 3D molecular visualization using py3Dmol"""
46
+ viewer = py3Dmol.view(width=400, height=300)
47
+ viewer.addModel(Chem.MolToMolBlock(Chem.MolFromSmiles(smiles)), 'smiles')
48
+ viewer.setStyle({'stick': {}, 'sphere': {'radius': 0.3}})
49
+ viewer.zoomTo()
50
+ html(viewer._make_html())
51
+
52
+ def calculate_molecular_properties(smiles: str):
53
+ """Calculate advanced molecular descriptors"""
54
  mol = Chem.MolFromSmiles(smiles)
55
  if mol:
56
+ try:
57
+ df = mordred_calculator.pandas([mol])
58
+ return df.iloc[0].to_dict()
59
+ except:
60
+ return {k: v(mol) for k, v in Descriptors.descList}
61
+
62
+ def predict_admet(smiles: str):
63
+ """Placeholder for actual ADMET prediction model"""
64
+ return {
65
+ 'BBB_Permeant': np.random.choice([True, False]),
66
+ 'CYP2D6_Inhibitor': np.random.choice([True, False]),
67
+ 'AMES_Toxicity': np.random.choice([True, False])
68
+ }
69
+
70
+ def quantum_simulation(smiles: str):
71
+ """Placeholder for quantum chemistry calculations"""
72
+ return {
73
+ 'HOMO_Energy': np.random.uniform(-15, -5),
74
+ 'LUMO_Energy': np.random.uniform(-3, 3),
75
+ 'Dipole_Moment': np.random.uniform(0, 5)
76
+ }
77
+
78
+ # --- Streamlit UI Components ---
79
+ def main():
80
+ st.title("🧪 Next-Gen Pharma Research Platform")
81
+ st.markdown("Integrated Drug Discovery & Development Analytics")
82
+
83
+ tabs = st.tabs([
84
+ "🚀 Molecular Explorer",
85
+ "📊 Clinical Analytics",
86
+ "⚗️ ADMET Predictor",
87
+ "🔬 Quantum Chemistry"
88
+ ])
89
+
90
+ with tabs[0]:
91
+ st.header("Molecular Discovery Studio")
92
+ compound_input = st.text_input("Enter compound identifier:", "Aspirin")
93
 
94
+ if st.button("Analyze Compound"):
95
+ col1, col2 = st.columns([2, 3])
96
+ with col1:
97
+ try:
98
+ compound = pcp.get_compounds(compound_input, 'name')[0]
99
+ st.subheader("2D Structure")
100
+ img = Draw.MolToImage(Chem.MolFromSmiles(compound.canonical_smiles))
101
+ st.image(img, caption=f"{compound.iupac_name}")
102
+
103
+ st.subheader("3D Visualization")
104
+ render_3d_molecule(compound.canonical_smiles)
105
+ except Exception as e:
106
+ st.error(f"Error rendering molecule: {str(e)}")
107
+
108
+ with col2:
109
+ st.subheader("Molecular Properties")
110
+ props = calculate_molecular_properties(compound.canonical_smiles)
111
+ prop_df = pd.DataFrame(list(props.items()), columns=['Property', 'Value'])
112
+ st.dataframe(prop_df.style.format({"Value": "{:.4f}"}), height=400)
113
+
114
+ st.subheader("Structural Similarity")
115
+ fig = px.scatter(x=[0.2, 0.7, 0.5], y=[0.8, 0.3, 0.6],
116
+ size=[10, 20, 15], color=['A', 'B', 'C'],
117
+ labels={'x': 'Feature 1', 'y': 'Feature 2'})
118
+ st.plotly_chart(fig)
119
+
120
+ with tabs[1]:
121
+ st.header("Clinical Trial Intelligence")
122
+ trial_query = st.text_input("Search clinical trials:", "COVID-19")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
 
124
+ if st.button("Analyze Trials"):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
  try:
126
+ response = requests.get(API_CONFIG['clinicaltrials']['url'],
127
+ params={**API_CONFIG['clinicaltrials']['params'],
128
+ "query": trial_query})
129
+ trials = response.json()['studies'][:5]
130
+
131
+ st.subheader("Top Clinical Trials")
132
+ trial_data = []
133
+ for study in trials:
134
+ trial_data.append({
135
+ 'NCT ID': study.get('protocolSection', {}).get('identificationModule', {}).get('nctId'),
136
+ 'Title': study.get('protocolSection', {}).get('identificationModule', {}).get('briefTitle'),
137
+ 'Phase': study.get('protocolSection', {}).get('designModule', {}).get('phase'),
138
+ 'Status': study.get('protocolSection', {}).get('statusModule', {}).get('overallStatus')
139
+ })
140
+ st.dataframe(pd.DataFrame(trial_data), use_container_width=True)
141
+
142
+ st.subheader("Trial Phase Distribution")
143
+ phase_counts = pd.DataFrame(trial_data)['Phase'].value_counts()
144
+ fig = px.pie(phase_counts, values=phase_counts.values, names=phase_counts.index)
145
+ st.plotly_chart(fig)
146
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
  except Exception as e:
148
+ st.error(f"Clinical trial search failed: {str(e)}")
149
 
150
+ with tabs[2]:
151
+ st.header("ADMET Prediction Engine")
152
+ smiles_input = st.text_input("Enter SMILES string:", "CC(=O)OC1=CC=CC=C1C(=O)O")
 
 
 
153
 
154
+ if st.button("Predict ADMET"):
155
+ with st.spinner("Running predictive models..."):
156
+ admet_props = predict_admet(smiles_input)
157
+
158
+ st.subheader("Prediction Results")
159
+ col1, col2, col3 = st.columns(3)
160
+ col1.metric("Blood-Brain Barrier",
161
+ "Permeant" if admet_props['BBB_Permeant'] else "Non-Permeant")
162
+ col2.metric("CYP2D6 Inhibition",
163
+ "Yes" if admet_props['CYP2D6_Inhibitor'] else "No")
164
+ col3.metric("AMES Toxicity",
165
+ "Toxic" if admet_props['AMES_Toxicity'] else "Safe")
166
+
167
+ st.subheader("Toxicity Risk Profile")
168
+ fig = px.bar(x=list(admet_props.keys()), y=[1, 0.5, 0.8],
169
+ labels={'x': 'Property', 'y': 'Risk Score'},
170
+ color_discrete_sequence=['#ff5252'])
171
+ st.plotly_chart(fig)
172
+
173
+ with tabs[3]:
174
+ st.header("Quantum Chemistry Simulations")
175
+ qc_smiles = st.text_input("Enter SMILES for simulation:", "C1CCCCC1")
 
 
 
 
 
 
 
 
 
 
 
 
176
 
177
+ if st.button("Run Quantum Analysis"):
178
+ with st.spinner("Performing quantum calculations..."):
179
+ qc_results = quantum_simulation(qc_smiles)
180
+
181
+ st.subheader("Quantum Properties")
182
+ col1, col2, col3 = st.columns(3)
183
+ col1.metric("HOMO Energy", f"{qc_results['HOMO_Energy']:.2f} eV")
184
+ col2.metric("LUMO Energy", f"{qc_results['LUMO_Energy']:.2f} eV")
185
+ col3.metric("Dipole Moment", f"{qc_results['Dipole_Moment']:.2f} D")
186
+
187
+ st.subheader("Molecular Orbitals")
188
+ fig = px.line(x=[-5, 0, 5], y=[qc_results['HOMO_Energy'], 0, qc_results['LUMO_Energy']],
189
+ labels={'x': 'Energy Level', 'y': 'Energy (eV)'})
190
+ st.plotly_chart(fig)
 
 
 
 
 
 
 
 
 
191
 
192
+ if __name__ == "__main__":
193
+ main()