Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -2,7 +2,7 @@ import streamlit as st
|
|
2 |
import torch
|
3 |
import os
|
4 |
from rdkit import Chem
|
5 |
-
from rdkit.Chem import Draw
|
6 |
from transformers import BartForConditionalGeneration, BartTokenizer
|
7 |
from admet_ai import ADMETModel
|
8 |
import safe
|
@@ -59,51 +59,24 @@ creativity = st.sidebar.slider(
|
|
59 |
num_molecules = st.sidebar.number_input(
|
60 |
'Number of Molecules to Generate:',
|
61 |
min_value=1,
|
62 |
-
max_value=5
|
63 |
-
value=
|
64 |
-
help="Select the number of molecules you want to generate."
|
65 |
-
)
|
66 |
-
|
67 |
-
# **String Format Option (SMILES or SAFE)**
|
68 |
-
string_format = st.sidebar.radio(
|
69 |
-
'String Format:',
|
70 |
-
('SMILES', 'SAFE'),
|
71 |
-
help="Choose the format for displaying molecule strings."
|
72 |
)
|
73 |
|
74 |
# **Function to Generate Molecule Images**
|
75 |
-
def generate_molecule_image(
|
76 |
"""
|
77 |
-
Generates an image of the molecule from the
|
78 |
-
Supports SAFE visualization if enabled.
|
79 |
"""
|
80 |
try:
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
smiles = safe.decode(input_string)
|
85 |
-
# **Encode back to SAFE string**
|
86 |
-
safe_string = safe.encode(smiles)
|
87 |
-
except Exception as e:
|
88 |
-
# **Handle decoding errors**
|
89 |
-
st.error(f"Error decoding SAFE string: {e}")
|
90 |
-
return None
|
91 |
-
# **Generate SVG image with fragment highlights**
|
92 |
-
svg_str = safe.to_image(safe_string)
|
93 |
-
# **Convert SVG to PNG bytes**
|
94 |
-
png_bytes = cairosvg.svg2png(bytestring=svg_str.encode('utf-8'))
|
95 |
-
# **Create an image object**
|
96 |
-
img = Image.open(io.BytesIO(png_bytes))
|
97 |
else:
|
98 |
-
|
99 |
-
mol = Chem.MolFromSmiles(input_string)
|
100 |
-
if mol:
|
101 |
-
img = Draw.MolToImage(mol, size=(200, 200)) # Adjusted size
|
102 |
-
else:
|
103 |
-
img = None
|
104 |
return img
|
105 |
except Exception as e:
|
106 |
-
# **Collect exceptions for later reporting**
|
107 |
st.error(f"Error generating molecule image: {e}")
|
108 |
return None
|
109 |
|
@@ -111,10 +84,15 @@ def generate_molecule_image(input_string, use_safe_visualization=True):
|
|
111 |
def st_copy_button(text, key):
|
112 |
"""
|
113 |
Creates a copy-to-clipboard button for the given text.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
114 |
"""
|
115 |
-
components.html(
|
116 |
-
<button onclick="navigator.clipboard.writeText('{text}')" style="padding:5px;">Copy</button>
|
117 |
-
""", height=45)
|
118 |
|
119 |
# **Generate Molecules Button**
|
120 |
if st.button('Generate Molecules'):
|
@@ -188,40 +166,72 @@ if st.button('Generate Molecules'):
|
|
188 |
# **Set 'Molecule Name' as index**
|
189 |
df_results.set_index('Molecule Name', inplace=True)
|
190 |
|
191 |
-
# **
|
192 |
-
|
193 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
194 |
else:
|
195 |
# **Display Molecules**
|
196 |
st.subheader('Generated Molecules')
|
197 |
|
198 |
# **Determine number of columns per row**
|
199 |
-
cols_per_row = min(
|
200 |
|
201 |
# **Create columns in Streamlit**
|
202 |
cols = st.columns(cols_per_row)
|
203 |
|
204 |
# **Iterate over each molecule to display**
|
205 |
-
for idx, (mol_name, row) in enumerate(
|
206 |
smiles = row['SMILES']
|
207 |
-
img = generate_molecule_image(
|
208 |
-
|
209 |
-
|
210 |
-
|
|
|
|
|
|
|
211 |
with cols[idx % cols_per_row]:
|
212 |
if img is not None and isinstance(img, Image.Image):
|
213 |
st.image(img, caption=mol_name)
|
214 |
else:
|
215 |
st.error(f"Could not generate image for {mol_name}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
216 |
# **Display molecule string in chosen format**
|
217 |
-
|
218 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
219 |
# **Copy-to-clipboard functionality**
|
220 |
-
st_copy_button(
|
221 |
-
|
|
|
|
|
|
|
|
|
222 |
st.write("**ADMET Properties:**")
|
223 |
-
|
|
|
|
|
224 |
else:
|
225 |
st.write("Click the 'Generate Molecules' button to generate beta-lactam molecules.")
|
226 |
-
|
227 |
-
|
|
|
2 |
import torch
|
3 |
import os
|
4 |
from rdkit import Chem
|
5 |
+
from rdkit.Chem import Draw, Descriptors
|
6 |
from transformers import BartForConditionalGeneration, BartTokenizer
|
7 |
from admet_ai import ADMETModel
|
8 |
import safe
|
|
|
59 |
num_molecules = st.sidebar.number_input(
|
60 |
'Number of Molecules to Generate:',
|
61 |
min_value=1,
|
62 |
+
max_value=3, # Reduced from 5 to 3
|
63 |
+
value=3,
|
64 |
+
help="Select the number of molecules you want to generate (up to 3)."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
)
|
66 |
|
67 |
# **Function to Generate Molecule Images**
|
68 |
+
def generate_molecule_image(smiles):
|
69 |
"""
|
70 |
+
Generates an image of the molecule from the SMILES string.
|
|
|
71 |
"""
|
72 |
try:
|
73 |
+
mol = Chem.MolFromSmiles(smiles)
|
74 |
+
if mol:
|
75 |
+
img = Draw.MolToImage(mol, size=(200, 200))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
76 |
else:
|
77 |
+
img = None
|
|
|
|
|
|
|
|
|
|
|
78 |
return img
|
79 |
except Exception as e:
|
|
|
80 |
st.error(f"Error generating molecule image: {e}")
|
81 |
return None
|
82 |
|
|
|
84 |
def st_copy_button(text, key):
|
85 |
"""
|
86 |
Creates a copy-to-clipboard button for the given text.
|
87 |
+
Adjusted to position the button without overlapping the text.
|
88 |
+
"""
|
89 |
+
# Adjusted styling to position the button
|
90 |
+
button_html = f"""
|
91 |
+
<div style="display: flex; justify-content: flex-end;">
|
92 |
+
<button onclick="navigator.clipboard.writeText('{text}')" style="padding:5px; margin-top: -40px; position: relative; z-index: 1;">Copy</button>
|
93 |
+
</div>
|
94 |
"""
|
95 |
+
components.html(button_html, height=45)
|
|
|
|
|
96 |
|
97 |
# **Generate Molecules Button**
|
98 |
if st.button('Generate Molecules'):
|
|
|
166 |
# **Set 'Molecule Name' as index**
|
167 |
df_results.set_index('Molecule Name', inplace=True)
|
168 |
|
169 |
+
# **Select only desired ADMET properties**
|
170 |
+
admet_properties = [
|
171 |
+
'molecular weight', 'logP', 'hydrogen_bond_acceptors',
|
172 |
+
'hydrogen_bond_donors', 'QED', 'ClinTox', 'hERG', 'BBB_Martins'
|
173 |
+
]
|
174 |
+
df_results_filtered = df_results[[
|
175 |
+
'SMILES', 'Valid'] + admet_properties]
|
176 |
+
|
177 |
+
# **Check if df_results_filtered is empty after filtering**
|
178 |
+
if df_results_filtered.empty:
|
179 |
+
st.error("No valid ADMET predictions were obtained. Please try adjusting the generation parameters.")
|
180 |
else:
|
181 |
# **Display Molecules**
|
182 |
st.subheader('Generated Molecules')
|
183 |
|
184 |
# **Determine number of columns per row**
|
185 |
+
cols_per_row = min(3, len(df_results_filtered)) # Max 3 columns
|
186 |
|
187 |
# **Create columns in Streamlit**
|
188 |
cols = st.columns(cols_per_row)
|
189 |
|
190 |
# **Iterate over each molecule to display**
|
191 |
+
for idx, (mol_name, row) in enumerate(df_results_filtered.iterrows()):
|
192 |
smiles = row['SMILES']
|
193 |
+
img = generate_molecule_image(smiles)
|
194 |
+
|
195 |
+
# **Initialize session state for toggle buttons**
|
196 |
+
toggle_key = f'toggle_{mol_name}'
|
197 |
+
if toggle_key not in st.session_state:
|
198 |
+
st.session_state[toggle_key] = False # False means SMILES is displayed
|
199 |
+
|
200 |
with cols[idx % cols_per_row]:
|
201 |
if img is not None and isinstance(img, Image.Image):
|
202 |
st.image(img, caption=mol_name)
|
203 |
else:
|
204 |
st.error(f"Could not generate image for {mol_name}")
|
205 |
+
|
206 |
+
# **Toggle Button to Switch Between SMILES and SAFE**
|
207 |
+
if st.button(
|
208 |
+
'Toggle to SAFE' if not st.session_state[toggle_key] else 'Toggle to SMILES',
|
209 |
+
key=toggle_key + '_button'
|
210 |
+
):
|
211 |
+
st.session_state[toggle_key] = not st.session_state[toggle_key]
|
212 |
+
|
213 |
# **Display molecule string in chosen format**
|
214 |
+
if st.session_state[toggle_key]:
|
215 |
+
# **Attempt to encode to SAFE**
|
216 |
+
try:
|
217 |
+
safe_string = safe.encode(smiles)
|
218 |
+
st.code(safe_string)
|
219 |
+
except Exception as e:
|
220 |
+
st.error(f"Could not convert to SAFE encoding: {e}")
|
221 |
+
st.code(smiles)
|
222 |
+
else:
|
223 |
+
st.code(smiles)
|
224 |
+
|
225 |
# **Copy-to-clipboard functionality**
|
226 |
+
st_copy_button(
|
227 |
+
safe_string if st.session_state[toggle_key] else smiles,
|
228 |
+
key=f'copy_{mol_name}'
|
229 |
+
)
|
230 |
+
|
231 |
+
# **Display selected ADMET properties**
|
232 |
st.write("**ADMET Properties:**")
|
233 |
+
# Drop 'SMILES' and 'Valid' columns for display
|
234 |
+
admet_data = row.drop(['SMILES', 'Valid'])
|
235 |
+
st.write(admet_data)
|
236 |
else:
|
237 |
st.write("Click the 'Generate Molecules' button to generate beta-lactam molecules.")
|
|
|
|