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.")
|
|
|
|
|
|