mgbam commited on
Commit
2213189
·
verified ·
1 Parent(s): 07c450c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +303 -152
app.py CHANGED
@@ -1,158 +1,309 @@
1
  import streamlit as st
2
- from smolagents import CodeAgent, ChatAgent
3
  from rdkit import Chem
4
- from rdkit.Chem import AllChem, Draw, Descriptors
5
- import py3Dmol
6
- from streamlit.components.v1 import html
7
- import pubchempy as pcp
8
  import requests
 
 
9
  import pandas as pd
10
- import numpy as np
11
- from io import BytesIO
12
- from st_cytoscape import cytoscape
13
-
14
- # Initialize AI Research Team
15
- class PharmaAITeam:
16
- def __init__(self):
17
- self.medicinal_chemist = CodeAgent(
18
- system="You are a senior medicinal chemist with 15+ years in lead optimization",
19
- tools=[MolecularDynamicsTool()]
20
- )
21
- self.clinical_strategist = ChatAgent(
22
- system="You are a clinical trial design expert with FDA/EMA experience"
23
- )
24
- self.bioinformatician = CodeAgent(
25
- system="You are a computational biology expert specializing in target validation",
26
- tools=[GenomeAnalysisTool()]
27
- )
28
-
29
- # AI-Powered Drug Discovery Platform
30
- st.set_page_config(page_title="NeuroPharm AI", layout="wide", page_icon="🧠")
31
- st.title("🧠 NeuroPharm AI: Next-Gen CNS Drug Discovery")
32
-
33
- # --- Innovative Modules ---
34
- with st.expander("🚀 AI Research Assistant", expanded=True):
35
- col1, col2 = st.columns([3,2])
36
- with col1:
37
- research_query = st.text_input("Ask your research question:",
38
- placeholder="Design a novel dopamine D3 selective agonist with reduced off-target effects")
39
- with col2:
40
- st.write("")
41
- if st.button("Generate Expert Response"):
42
- with st.spinner("Consulting AI research team..."):
43
- team = PharmaAITeam()
44
- chem_response = team.medicinal_chemist.run(research_query)
45
- clinical_context = team.clinical_strategist.run(f"Provide clinical development considerations for: {research_query}")
46
-
47
- st.markdown(f"""
48
- **Medicinal Chemistry Insights**
49
- ```{chem_response}```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
 
51
- **Clinical Development Strategy**
52
- ```{clinical_context}```
53
- """)
54
-
55
- # --- Quantum Molecular Studio ---
56
- st.subheader("🔬 Quantum Molecular Studio")
57
- col1, col2, col3 = st.columns([2,3,2])
58
-
59
- with col1:
60
- compound = st.text_input("Enter compound:", "Risperidone")
61
- if st.button("Run Quantum Analysis"):
62
- with st.spinner("Performing QM/MM simulations..."):
63
- mol = pcp.get_compounds(compound, 'name')[0]
64
- st.session_state.mol3d = AllChem.AddHs(Chem.MolFromSmiles(mol.canonical_smiles))
65
- AllChem.EmbedMolecule(st.session_state.mol3d, randomSeed=0xf00d)
66
- AllChem.MMFFOptimizeMolecule(st.session_state.mol3d)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
 
68
- # Generate interactive 3D viewer
69
- viewer = py3Dmol.view(width=400, height=300)
70
- viewer.addModel(Chem.MolToMolBlock(st.session_state.mol3d), 'mol')
71
- viewer.setStyle({'stick': {}, 'sphere': {'radius': 0.3}})
72
- viewer.zoomTo()
73
- html(viewer._make_html())
74
-
75
- # Generate pharmacological profile
76
- descriptors = {
77
- 'QPlogPo/w': np.random.uniform(2,5),
78
- 'CNS Activity': np.random.choice(['High', 'Medium', 'Low']),
79
- 'Blood-Brain Barrier': 'Yes' if Descriptors.MolLogP(st.session_state.mol3d) > 2 else 'No'
80
- }
81
- st.session_state.descriptors = descriptors
82
-
83
- with col2:
84
- if 'mol3d' in st.session_state:
85
- st.markdown("**Quantum Properties Prediction**")
86
- cyto_elements = [
87
- {'data': {'id': 'HOMO', 'label': f'HOMO: {np.random.uniform(-9,-5):.2f} eV'}},
88
- {'data': {'id': 'LUMO', 'label': f'LUMO: {np.random.uniform(-3,1):.2f} eV'}},
89
- {'data': {'source': 'HOMO', 'target': 'LUMO'}}
90
- ]
91
- cytoscape(
92
- elements=cyto_elements,
93
- layout={'name': 'circle'},
94
- stylesheet=[{
95
- 'selector': 'node',
96
- 'style': {'label': 'data(label)', 'font-size': '20px'}
97
- }],
98
- height="300px"
99
- )
100
-
101
- with col3:
102
- if 'descriptors' in st.session_state:
103
- st.markdown("**Pharmacokinetic Profile**")
104
- for k, v in st.session_state.descriptors.items():
105
- st.metric(k, v)
106
- st.plotly_chart(px.bar(
107
- x=list(st.session_state.descriptors.keys()),
108
- y=[1, 0.7, 0.9],
109
- title="Blood-Brain Barrier Penetration Potential"
110
- ))
111
-
112
- # --- Neural Target Mapping ---
113
- st.subheader("🧫 Neuro-Target Interaction Network")
114
- if st.button("Map CNS Targets"):
115
- with st.spinner("Analyzing human brain proteome..."):
116
- nodes = [
117
- {'data': {'id': 'D2', 'label': 'Dopamine D2'}},
118
- {'data': {'id': '5HT2A', 'label': '5-HT2A'}},
119
- {'data': {'id': 'H1', 'label': 'Histamine H1'}},
120
- {'data': {'id': compound, 'label': compound}}
121
- ]
122
- edges = [
123
- {'data': {'source': compound, 'target': 'D2', 'label': 'Kd=4.2nM'}},
124
- {'data': {'source': compound, 'target': '5HT2A', 'label': 'Kd=18nM'}},
125
- {'data': {'source': compound, 'target': 'H1', 'label': 'Kd=2.1μM'}}
126
- ]
127
- cytoscape(
128
- elements=nodes + edges,
129
- layout={'name': 'cose'},
130
- stylesheet=[
131
- {
132
- 'selector': 'node',
133
- 'style': {'label': 'data(label)', 'shape': 'hexagon'}
134
- },
135
- {
136
- 'selector': 'edge',
137
- 'style': {'label': 'data(label)', 'curve-style': 'bezier'}
138
- }
139
- ],
140
- height="400px"
141
- )
142
-
143
- # --- Virtual Clinical Trial Simulator ---
144
- st.subheader("📈 AI Clinical Trial Predictor")
145
- col1, col2 = st.columns(2)
146
- with col1:
147
- phase = st.selectbox("Trial Phase", ["Phase I", "Phase II", "Phase III"])
148
- population = st.slider("Patient Population", 50, 5000, 200)
149
- with col2:
150
- endpoints = st.multiselect("Endpoints", ["PANSS", "MADRS", "CGI-S", "Neurocognitive Battery"])
151
- if st.button("Predict Trial Outcome"):
152
- with st.spinner("Running Monte Carlo simulations..."):
153
- success_prob = np.random.uniform(0.3, 0.8)
154
- st.metric("Predicted Success Probability", f"{success_prob:.0%}")
155
- st.altair_chart(alt.Chart(pd.DataFrame({
156
- 'Week': range(1,13),
157
- 'Improvement': np.cumsum(np.random.normal(0.5, 0.2, 12))
158
- })).mark_line().encode(x='Week', y='Improvement'))
 
1
  import streamlit as st
2
+ from smolagents import CodeAgent, DuckDuckGoSearchTool, HfApiModel
3
  from rdkit import Chem
4
+ from rdkit.Chem import Draw
5
+ from fpdf import FPDF
6
+ import tempfile
7
+ import time
8
  import requests
9
+ import xml.etree.ElementTree as ET
10
+ import json
11
  import pandas as pd
12
+ import matplotlib.pyplot as plt
13
+ import seaborn as sns
14
+ from typing import Optional, Dict, List, Any
15
+
16
+
17
+ # API Endpoints (Centralized Configuration)
18
+ API_ENDPOINTS = {
19
+ "clinical_trials": "https://clinicaltrials.gov/api/query/full_studies",
20
+ "pubchem": "https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/name/{}/JSON",
21
+ "who_drugs": "https://health-products.canada.ca/api/drug/product",
22
+ "ema_reports": "https://www.ema.europa.eu/api/search/medicines",
23
+ "fda_drug_approval": "https://api.fda.gov/drug/label.json?search=openfda.brand_name:{}",
24
+ "faers_adverse_events": "https://api.fda.gov/drug/event.json?search=patient.drug.medicinalproduct:{}",
25
+ "pharmgkb": "https://api.pharmgkb.org/v1/site/variant/{}/clinicalAnnotations"
26
+ }
27
+
28
+
29
+ # Initialize AI Agent (Context-aware)
30
+ content_agent = CodeAgent(tools=[DuckDuckGoSearchTool()], model=HfApiModel())
31
+
32
+ # --- Utility Functions ---
33
+ def _query_api(endpoint: str, params: Optional[Dict] = None) -> Optional[Dict]:
34
+ """Handles API requests with robust error handling."""
35
+ try:
36
+ response = requests.get(endpoint, params=params, timeout=15)
37
+ response.raise_for_status() # Raise HTTPError for bad responses (4xx or 5xx)
38
+ return response.json()
39
+ except requests.exceptions.RequestException as e:
40
+ st.error(f"API request failed: {e} for endpoint {endpoint}. Please check connectivity and the endpoint.")
41
+ return None
42
+
43
+
44
+ def _get_pubchem_smiles(drug_name: str) -> Optional[str]:
45
+ """Retrieves SMILES from PubChem, returns None on failure."""
46
+ url = API_ENDPOINTS["pubchem"].format(drug_name)
47
+ data = _query_api(url)
48
+ if data and 'PC_Compounds' in data and data['PC_Compounds'][0]['props']:
49
+ #Check if props exists and find SMILES value
50
+ for prop in data['PC_Compounds'][0]['props']:
51
+ if 'name' in prop and prop['name'] == 'Canonical SMILES':
52
+ return prop['value']['sval']
53
+ return None
54
+
55
+
56
+ def _draw_molecule(smiles: str) -> Optional[any]:
57
+ """Generates a 2D molecule image from SMILES."""
58
+ try:
59
+ mol = Chem.MolFromSmiles(smiles)
60
+ if mol:
61
+ img = Draw.MolToImage(mol)
62
+ return img
63
+ else:
64
+ st.error("Invalid SMILES string.")
65
+ return None
66
+ except Exception as e:
67
+ st.error(f"Error generating molecule image: {str(e)}")
68
+ return None
69
+
70
+
71
+ def _get_clinical_trials(query: str) -> Optional[Dict]:
72
+ """Queries clinicaltrials.gov with search term."""
73
+ if query.upper().startswith("NCT") and query[3:].isdigit(): # Check if it's an NCT number
74
+ params = {
75
+ "id": query,
76
+ "fmt": "json"
77
+ }
78
+ else:
79
+ params = {
80
+ "expr": query,
81
+ "min_rnk": 1,
82
+ "max_rnk": 5,
83
+ "fmt": "json"
84
+ }
85
+ return _query_api(API_ENDPOINTS["clinical_trials"], params)
86
+
87
+ def _get_fda_approval(drug_name: str) -> Optional[Dict]:
88
+ """Retrieves FDA approval info."""
89
+ url = API_ENDPOINTS["fda_drug_approval"].format(drug_name)
90
+ data = _query_api(url)
91
+ return data['results'][0] if data and 'results' in data and data['results'] else None
92
+
93
+
94
+ def _analyze_adverse_events(drug_name: str) -> Optional[Dict]:
95
+ """Fetches and analyzes adverse event reports from FAERS."""
96
+ url = API_ENDPOINTS["faers_adverse_events"].format(drug_name)
97
+ return _query_api(url)
98
+
99
+
100
+ def _get_pharmgkb_data(gene:str) -> Optional[Dict]:
101
+ """Fetches pharmacogenomic data from PharmGKB."""
102
+ url = "https://api.pharmgkb.org/v1/data/variant/{}/clinicalAnnotations".format(gene)
103
+ return _query_api(url)
104
+
105
+
106
+ def _save_pdf_report(report_content: str, filename: str):
107
+ """Saves content to a PDF file."""
108
+ pdf = FPDF()
109
+ pdf.add_page()
110
+ pdf.set_font("Arial", size=12)
111
+ pdf.multi_cell(0, 10, report_content)
112
+ pdf.output(filename)
113
+ return filename
114
+
115
+ def _display_dataframe(data: list, columns: list):
116
+ """Displays data in a dataframe format."""
117
+ if data:
118
+ df = pd.DataFrame(data, columns=columns)
119
+ st.dataframe(df)
120
+ return df
121
+ else:
122
+ st.warning("No data found for dataframe creation.")
123
+ return None
124
+
125
+ # --- Streamlit App Configuration ---
126
+ st.set_page_config(page_title="Pharma Research Expert Platform", layout="wide")
127
+ st.title("🔬 Pharma Research Expert Platform")
128
+ st.markdown("An integrated platform for drug discovery, clinical research, and regulatory affairs.")
129
+
130
+ # --- Tabs ---
131
+ tabs = st.tabs(["💊 Drug Development", "📊 Trial Analytics", "🧬 Molecular Profiling", "📜 Regulatory Intelligence"])
132
+
133
+ # --- Tab 1: Drug Development ---
134
+ with tabs[0]:
135
+ st.header("AI-Driven Drug Development Strategy")
136
+ target = st.text_input("Target Disease/Pathway:", placeholder="Enter biological target or disease mechanism")
137
+ target_gene = st.text_input("Target Gene (for pharmacogenomics)", placeholder="Enter the gene associated with target")
138
+ strategy = st.selectbox("Development Strategy:", ["First-in-class", "Me-too", "Repurposing", "Biologic"])
139
+
140
+ if st.button("Generate Development Plan"):
141
+ with st.spinner("Analyzing target and competitive landscape..."):
142
+ # AI-generated content with regulatory checks
143
+ plan_prompt = f"""Develop a comprehensive drug development plan for the treatment of {target} using a {strategy} strategy.
144
+ Include sections on target validation, lead optimization, preclinical testing, clinical trial design, regulatory submission strategy, market analysis, and competitive landscape. Highlight key milestones and potential challenges. """
145
+ plan = content_agent.run(plan_prompt)
146
+
147
+ st.subheader("Comprehensive Development Plan")
148
+ st.markdown(plan)
149
+
150
+ # Regulatory information
151
+ if target:
152
+ fda_info = _get_fda_approval(target.split()[0]) # Simple name extraction for FDA search
153
+
154
+ if fda_info:
155
+ st.subheader("FDA Regulatory Insights")
156
+ st.json(fda_info)
157
+ else:
158
+ st.write("No relevant FDA data found.")
159
+ else:
160
+ st.write("Please enter a target to get relevant FDA data")
161
+
162
+ # Pharmacogenomic integration
163
+ st.subheader("Pharmacogenomic Considerations")
164
+ pgx_data = _get_pharmgkb_data(target_gene)
165
+ if pgx_data:
166
+ st.write(pgx_data)
167
+ else:
168
+ st.write("No relevant pharmacogenomic data found.")
169
+
170
+
171
+ # --- Tab 2: Clinical Trial Analytics ---
172
+ with tabs[1]:
173
+ st.header("Clinical Trial Landscape Analytics")
174
+ trial_query = st.text_input("Search Clinical Trials:", placeholder="Enter condition, intervention, or NCT number")
175
+
176
+ if st.button("Analyze Trial Landscape"):
177
+ with st.spinner("Aggregating global trial data..."):
178
+ trials = _get_clinical_trials(trial_query)
179
+ if trials and trials['FullStudiesResponse']['FullStudies']:
180
+ st.subheader("Recent Clinical Trials")
181
+ trial_data = []
182
+ for study in trials['FullStudiesResponse']['FullStudies'][:5]:
183
+ protocol = study['Study']['ProtocolSection']
184
+ trial_data.append({
185
+ "Title": protocol['IdentificationModule']['OfficialTitle'],
186
+ "Status": protocol['StatusModule']['OverallStatus'],
187
+ "Phase": protocol['DesignModule']['PhaseList']['Phase'][0],
188
+ "Enrollment": protocol['StatusModule']['EnrollmentCount']
189
+ })
190
 
191
+ trial_df = _display_dataframe(trial_data, list(trial_data[0].keys())) if trial_data else None
192
+
193
+ if trial_df is not None:
194
+ st.markdown("### Clinical Trial Summary (First 5 trials)")
195
+ st.dataframe(trial_df)
196
+
197
+
198
+ # Adverse events analysis
199
+ ae_data = _analyze_adverse_events(trial_query)
200
+ if ae_data and ae_data['results']:
201
+ st.subheader("Adverse Event Profile (Top 5 Reports)")
202
+
203
+ ae_results = ae_data['results'][:5]
204
+ ae_df = pd.DataFrame(ae_results)
205
+ st.dataframe(ae_df)
206
+
207
+ #Visualization of adverse events
208
+ if 'patient' in ae_df and not ae_df.empty:
209
+ try:
210
+ drug_events = []
211
+ for patient in ae_df['patient']:
212
+ if isinstance(patient,dict) and 'drug' in patient:
213
+ for drug in patient['drug']:
214
+ if isinstance(drug,dict) and 'medicinalproduct' in drug and 'reaction' in patient:
215
+ reactions = [reaction.get('reactionmeddrapt','') for reaction in patient['reaction']]
216
+ for r in reactions:
217
+ drug_events.append((drug.get('medicinalproduct', 'N/A'), r))
218
+
219
+ df_drug_events = pd.DataFrame(drug_events,columns=['Drug', 'Reaction'])
220
+ # Aggregate and Visualize top reactions
221
+ if not df_drug_events.empty:
222
+ top_reactions = df_drug_events['Reaction'].value_counts().nlargest(10)
223
+
224
+ fig, ax = plt.subplots(figsize=(10,6))
225
+ sns.barplot(x=top_reactions.index, y=top_reactions.values, ax=ax)
226
+ ax.set_xticklabels(ax.get_xticklabels(), rotation=45, ha="right")
227
+ plt.title('Top Adverse Reactions')
228
+ plt.xlabel('Adverse Reaction')
229
+ plt.ylabel('Frequency')
230
+ st.pyplot(fig)
231
+
232
+ #Display as dataframe
233
+ st.markdown("### Top 10 Adverse Reaction Summary")
234
+ st.dataframe(pd.DataFrame({'Reaction': top_reactions.index, 'Frequency': top_reactions.values}))
235
+
236
+ except Exception as e:
237
+ st.error(f"Error processing adverse events data: {e}")
238
+ else:
239
+ st.warning("No clinical trials found for the given search term.")
240
+
241
+
242
+ # --- Tab 3: Molecular Profiling ---
243
+ with tabs[2]:
244
+ st.header("Advanced Molecular Profiling")
245
+ compound_input = st.text_input("Compound Identifier:",
246
+ placeholder="Enter drug name, SMILES, or INN")
247
+
248
+ if st.button("Analyze Compound"):
249
+ with st.spinner("Querying global databases..."):
250
+ # SMILES resolution
251
+ smiles = compound_input if Chem.MolFromSmiles(compound_input) else _get_pubchem_smiles(compound_input)
252
+
253
+ if smiles:
254
+ img = _draw_molecule(smiles)
255
+ if img:
256
+ st.image(img, caption="2D Structure")
257
+ else:
258
+ st.error("Compound structure not found in databases.")
259
+
260
+ # PubChem properties
261
+ pubchem_data = _query_api(API_ENDPOINTS["pubchem"].format(compound_input))
262
+ if pubchem_data and 'PC_Compounds' in pubchem_data and pubchem_data['PC_Compounds']:
263
+ st.subheader("Physicochemical Properties")
264
+ props = pubchem_data['PC_Compounds'][0]['props']
265
+ mw = next((prop['value']['sval'] for prop in props if 'name' in prop and prop['name'] == 'Molecular Weight'), 'N/A')
266
+ logp = next((prop['value']['sval'] for prop in props if 'name' in prop and prop['name'] == 'LogP'), 'N/A')
267
+
268
+ st.write(f"""
269
+ Molecular Weight: {mw}
270
+ LogP: {logp}
271
+ """)
272
+ else:
273
+ st.error("Physicochemical properties not found.")
274
+
275
+
276
+ # --- Tab 4: Regulatory Intelligence ---
277
+ with tabs[3]:
278
+ st.header("Global Regulatory Monitoring")
279
+ drug_name = st.text_input("Drug Product:", placeholder="Enter generic or brand name")
280
+
281
+ if st.button("Generate Regulatory Report"):
282
+ with st.spinner("Compiling global regulatory status..."):
283
+ # Multi-regional checks
284
+ fda = _get_fda_approval(drug_name)
285
+ ema = _query_api(API_ENDPOINTS["ema_reports"], {"search": drug_name})
286
+ who = _query_api(API_ENDPOINTS["who_drugs"], {"name": drug_name})
287
 
288
+ st.subheader("Regulatory Status")
289
+ col1, col2, col3 = st.columns(3)
290
+ with col1:
291
+ st.markdown("**FDA Status**")
292
+ st.write(fda['openfda']['brand_name'][0] if fda and 'openfda' in fda and 'brand_name' in fda['openfda'] else "Not approved")
293
+ with col2:
294
+ st.markdown("**EMA Status**")
295
+ st.write(ema['results'][0]['currentStatus'] if ema and 'results' in ema and ema['results'] else "Not approved")
296
+ with col3:
297
+ st.markdown("**WHO Essential Medicine**")
298
+ st.write("Yes" if who else "No")
299
+
300
+ # Save the information to a PDF report
301
+ regulatory_content = f"### Regulatory Report\n\nFDA Status: {fda['openfda']['brand_name'][0] if fda and 'openfda' in fda and 'brand_name' in fda['openfda'] else 'Not Approved'}\n\nEMA Status: {ema['results'][0]['currentStatus'] if ema and 'results' in ema and ema['results'] else 'Not Approved'}\n\nWHO Essential Medicine: {'Yes' if who else 'No'}"
302
+ report_file = _save_pdf_report(regulatory_content, f"{drug_name}_regulatory_report.pdf")
303
+ if report_file:
304
+ with open(report_file, "rb") as file:
305
+ st.download_button(
306
+ label="Download Regulatory Report (PDF)",
307
+ data=file,
308
+ file_name=f"{drug_name}_regulatory_report.pdf",
309
+ mime="application/pdf")