mgbam commited on
Commit
e69190c
·
verified ·
1 Parent(s): 276129d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +115 -156
app.py CHANGED
@@ -1,193 +1,152 @@
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()
 
1
  import streamlit as st
2
  import py3Dmol
3
  from rdkit import Chem
4
+ from rdkit.Chem import Draw, Descriptors, AllChem
 
5
  import pandas as pd
 
6
  import requests
 
 
7
  from PIL import Image
8
+ import json
9
  from io import BytesIO
 
10
  from streamlit.components.v1 import html
 
11
  import pubchempy as pcp
 
12
 
13
+ # --- Hugging Face Optimized Configuration ---
14
+ st.set_page_config(page_title="PharmaAI HF", layout="wide", page_icon="🧪")
15
  st.markdown("""
16
  <style>
17
+ .stApp { background-color: #f8f9fa }
18
+ .block-container { padding-top: 2rem }
19
+ h1 { color: #1e3d59 }
20
+ .stButton>button { background-color: #4CAF50; color: white }
21
  </style>
22
  """, unsafe_allow_html=True)
23
 
24
+ # --- Lightweight API Config ---
25
  API_CONFIG = {
26
  "pubchem": "https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/name/{}/JSON",
27
+ "clinicaltrials": "https://clinicaltrials.gov/api/query/full_studies?expr={}&fmt=json",
28
+ "chembl": "https://www.ebi.ac.uk/chembl/api/data/molecule?pref_name__iexact={}"
 
 
 
 
29
  }
30
 
31
+ # --- Core Functions with Caching ---
32
+ @st.cache_data(ttl=3600)
33
+ def get_pubchem_data(name):
34
+ try:
35
+ return pcp.get_compounds(name, 'name')[0]
36
+ except Exception as e:
37
+ st.error(f"PubChem error: {str(e)}")
38
+ return None
39
+
40
+ @st.cache_data(ttl=3600)
41
+ def get_clinical_trials(query):
42
+ try:
43
+ response = requests.get(API_CONFIG["clinicaltrials"].format(query))
44
+ return json.loads(response.text)["FullStudiesResponse"]["FullStudies"][:5]
45
+ except Exception as e:
46
+ st.error(f"Clinical Trials API error: {str(e)}")
47
+ return []
48
+
49
+ def render_3d(smiles):
50
  viewer = py3Dmol.view(width=400, height=300)
51
  viewer.addModel(Chem.MolToMolBlock(Chem.MolFromSmiles(smiles)), 'smiles')
52
  viewer.setStyle({'stick': {}, 'sphere': {'radius': 0.3}})
53
  viewer.zoomTo()
54
  html(viewer._make_html())
55
 
56
+ # --- Streamlit App ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  def main():
58
+ st.title("🧬 Pharma Research Hub")
59
+ st.markdown("Drug Discovery Platform Optimized for Hugging Face Spaces")
60
+
61
+ tab1, tab2, tab3, tab4 = st.tabs(["Molecule Analysis", "Clinical Trials", "ADMET Prediction", "About"])
62
+
63
+ with tab1:
64
+ col1, col2 = st.columns([1, 2])
65
+ with col1:
66
+ compound = st.text_input("Enter compound name:", "Aspirin")
67
+ if st.button("Analyze"):
68
+ with st.spinner("Fetching data..."):
69
+ mol_data = get_pubchem_data(compound)
70
+
71
+ if mol_data:
72
+ st.session_state.mol = mol_data
73
+ with col2:
74
+ st.subheader("3D Visualization")
75
+ render_3d(mol_data.canonical_smiles)
76
 
77
+ if 'mol' in st.session_state:
78
+ mol = st.session_state.mol
79
+ st.subheader(f"Properties for {mol.iupac_name}")
80
+
81
+ col1, col2, col3 = st.columns(3)
82
  with col1:
83
+ st.image(Draw.MolToImage(Chem.MolFromSmiles(mol.canonical_smiles)),
84
+ caption="2D Structure", width=200)
85
+
 
 
 
 
 
 
 
 
86
  with col2:
87
+ st.markdown("**Basic Properties**")
88
+ st.write(f"Molecular Formula: {mol.molecular_formula}")
89
+ st.write(f"Weight: {mol.molecular_weight:.2f} g/mol")
90
+ st.write(f"LogP: {mol.xlogp}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
 
92
+ with col3:
93
+ st.markdown("**Advanced Features**")
94
+ rdkit_mol = Chem.MolFromSmiles(mol.canonical_smiles)
95
+ st.write(f"H-Bond Donors: {Descriptors.NumHDonors(rdkit_mol)}")
96
+ st.write(f"Rotatable Bonds: {Descriptors.NumRotatableBonds(rdkit_mol)}")
97
+ st.write(f"TPSA: {Descriptors.TPSA(rdkit_mol):.2f}")
98
+
99
+ with tab2:
100
+ trial_query = st.text_input("Search clinical trials:", "Cancer")
101
+ if st.button("Find Trials"):
102
+ trials = get_clinical_trials(trial_query)
103
+
104
+ if trials:
105
+ st.subheader("Recent Clinical Trials")
106
  for study in trials:
107
+ info = study["Study"]["ProtocolSection"]
108
+ st.markdown(f"""
109
+ **{info["IdentificationModule"]["OfficialTitle"]}**
110
+ - Status: {info["StatusModule"]["OverallStatus"]}
111
+ - Phase: {info["DesignModule"].get("Phase", "N/A")}
112
+ - Interventions: {", ".join([i["InterventionName"] for i in info["ArmsInterventionsModule"]["Interventions"]])}
113
+ """)
114
+ else:
115
+ st.warning("No trials found for this search term")
116
+
117
+ with tab3:
118
+ st.subheader("ADMET Prediction (Demo)")
119
+ if 'mol' in st.session_state:
120
+ col1, col2 = st.columns(2)
121
+ with col1:
122
+ st.markdown("**Absorption**")
123
+ st.progress(0.75)
124
+ st.caption("Predicted Bioavailability: 75%")
 
 
 
 
 
125
 
126
+ st.markdown("**Distribution**")
127
+ st.progress(0.82)
128
+ st.caption("Plasma Protein Binding: 82%")
 
 
 
 
 
129
 
130
+ with col2:
131
+ st.markdown("**Metabolism**")
132
+ st.progress(0.68)
133
+ st.caption("CYP3A4 Substrate Probability: 68%")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
 
135
+ st.markdown("**Toxicity**")
136
+ st.progress(0.15)
137
+ st.caption("AMES Mutagenicity Risk: 15%")
138
+ else:
139
+ st.info("Analyze a compound first in the 'Molecule Analysis' tab")
140
+
141
+ with tab4:
142
+ st.markdown("""
143
+ ## About This Platform
144
+ **Pharma Research Hub** - Optimized for Hugging Face Spaces
145
+ - Built with Streamlit
146
+ - Integrates PubChem, ClinicalTrials.gov
147
+ - Molecular visualization with RDKit and py3Dmol
148
+ - Lightweight architecture for HF Spaces
149
+ """)
150
 
151
  if __name__ == "__main__":
152
  main()