Nanny7 commited on
Commit
a1cee59
·
1 Parent(s): 5ecdd8c

Add reaction visualizer API endpoint and improve error handling

Browse files
Files changed (2) hide show
  1. .gitignore +84 -0
  2. app.py +53 -4
.gitignore ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ develop-eggs/
9
+ dist/
10
+ downloads/
11
+ eggs/
12
+ .eggs/
13
+ lib/
14
+ lib64/
15
+ parts/
16
+ sdist/
17
+ var/
18
+ wheels/
19
+ *.egg-info/
20
+ .installed.cfg
21
+ *.egg
22
+ MANIFEST
23
+
24
+ # PyInstaller
25
+ *.manifest
26
+ *.spec
27
+
28
+ # Installer logs
29
+ pip-log.txt
30
+ pip-delete-this-directory.txt
31
+
32
+ # Unit test / coverage reports
33
+ htmlcov/
34
+ .tox/
35
+ .coverage
36
+ .coverage.*
37
+ .cache
38
+ nosetests.xml
39
+ coverage.xml
40
+ *.cover
41
+ .hypothesis/
42
+ .pytest_cache/
43
+
44
+ # Jupyter Notebook
45
+ .ipynb_checkpoints
46
+
47
+ # pyenv
48
+ .python-version
49
+
50
+ # celery beat schedule file
51
+ celerybeat-schedule
52
+
53
+ # SageMath parsed files
54
+ *.sage.py
55
+
56
+ # Environments
57
+ .env
58
+ .venv
59
+ env/
60
+ venv/
61
+ ENV/
62
+ env.bak/
63
+ venv.bak/
64
+
65
+ # IDE
66
+ .vscode/
67
+ .idea/
68
+ *.swp
69
+ *.swo
70
+ *~
71
+
72
+ # OS
73
+ .DS_Store
74
+ .DS_Store?
75
+ ._*
76
+ .Spotlight-V100
77
+ .Trashes
78
+ ehthumbs.db
79
+ Thumbs.db
80
+
81
+ # Temporary files
82
+ *.tmp
83
+ *.temp
84
+ .cache/
app.py CHANGED
@@ -92,6 +92,7 @@ def parse_cube_file(cube_file):
92
  import gradio as gr
93
  from rdkit import Chem
94
  from rdkit.Chem import Descriptors, Draw, AllChem
 
95
  import cirpy
96
  import pubchempy as pcp
97
  from urllib.error import HTTPError, URLError
@@ -149,6 +150,8 @@ def name_to_smiles(name: str) -> str:
149
  if smiles is None:
150
  raise gr.Error(f"Could not find SMILES for chemical name: {name}")
151
  return smiles
 
 
152
  except Exception as e:
153
  raise gr.Error(f"Error converting name to SMILES: {str(e)}")
154
 
@@ -184,6 +187,23 @@ def smiles_to_name(smiles: str) -> str:
184
  return f"No name available. Canonical SMILES: {canonical_smiles}"
185
 
186
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
187
  CHEMISCOPE_TEMPLATE_URL = "https://chemiscope.org/chemiscope_standalone.html"
188
  CHEMISCOPE_TEMPLATE_CACHE = Path(tempfile.gettempdir()) / "chemiscope_standalone.html"
189
  CHEMISCOPE_ASSET_DIR = Path("chemiscope_artifacts")
@@ -686,10 +706,15 @@ def smiles_to_molecular_orbitals(smiles_input: str, name_input: str) -> str:
686
  def name_to_3d_molecule(name: str) -> str:
687
  """Convert chemical name to 3D molecule visualization"""
688
  try:
689
- # Convert name to SMILES
690
- smiles = cirpy.resolve(name, 'smiles')
691
- if smiles is None:
692
- raise gr.Error(f"Could not find SMILES for chemical name: {name}")
 
 
 
 
 
693
 
694
  # Create molecule from SMILES
695
  mol = Chem.MolFromSmiles(smiles)
@@ -733,6 +758,9 @@ def name_to_3d_molecule(name: str) -> str:
733
 
734
  return html_content
735
 
 
 
 
736
  except Exception as e:
737
  raise gr.Error(f"Error creating 3D molecule: {str(e)}")
738
 
@@ -1268,6 +1296,25 @@ scaffold_interface = gr.Interface(
1268
  examples=[["c1ccc(CCN)cc1\nc1ccc(CCO)cc1\nc1ccc(CCC)cc1\nCCOc1ccc(CCN)cc1\nCCc1ccc(O)cc1"]],
1269
  )
1270
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1271
 
1272
  demo = gr.TabbedInterface(
1273
  [
@@ -1276,6 +1323,7 @@ demo = gr.TabbedInterface(
1276
  properties_interface,
1277
  clustering_interface,
1278
  scaffold_interface,
 
1279
  name_interface,
1280
  molecule_3d_interface,
1281
  chemiscope_interface,
@@ -1291,6 +1339,7 @@ demo = gr.TabbedInterface(
1291
  "Property Calculator",
1292
  "Molecular Clustering",
1293
  "Scaffold Analysis",
 
1294
  "Name to SMILES",
1295
  "3D Molecule Viewer",
1296
  "Chemiscope Explorer",
 
92
  import gradio as gr
93
  from rdkit import Chem
94
  from rdkit.Chem import Descriptors, Draw, AllChem
95
+ from rdkit.Chem import rdChemReactions
96
  import cirpy
97
  import pubchempy as pcp
98
  from urllib.error import HTTPError, URLError
 
150
  if smiles is None:
151
  raise gr.Error(f"Could not find SMILES for chemical name: {name}")
152
  return smiles
153
+ except (HTTPError, URLError) as e:
154
+ raise gr.Error(f"Unable to connect to chemical database service. Please try again later. Error: {str(e)}")
155
  except Exception as e:
156
  raise gr.Error(f"Error converting name to SMILES: {str(e)}")
157
 
 
187
  return f"No name available. Canonical SMILES: {canonical_smiles}"
188
 
189
 
190
+ def reaction_smiles_to_svg(reaction_smiles: str) -> str:
191
+ """Convert reaction SMILES to SVG image"""
192
+ try:
193
+ # Parse the reaction SMILES
194
+ reaction = rdChemReactions.ReactionFromSmarts(reaction_smiles)
195
+ if reaction is None:
196
+ raise gr.Error(f"Invalid reaction SMILES: {reaction_smiles}")
197
+
198
+ # Draw the reaction as SVG
199
+ svg = Draw.ReactionToImage(reaction, subImgSize=(300, 300), useSVG=True)
200
+
201
+ return svg
202
+
203
+ except Exception as e:
204
+ raise gr.Error(f"Error generating reaction image: {str(e)}")
205
+
206
+
207
  CHEMISCOPE_TEMPLATE_URL = "https://chemiscope.org/chemiscope_standalone.html"
208
  CHEMISCOPE_TEMPLATE_CACHE = Path(tempfile.gettempdir()) / "chemiscope_standalone.html"
209
  CHEMISCOPE_ASSET_DIR = Path("chemiscope_artifacts")
 
706
  def name_to_3d_molecule(name: str) -> str:
707
  """Convert chemical name to 3D molecule visualization"""
708
  try:
709
+ # Convert name to SMILES with better error handling
710
+ try:
711
+ smiles = cirpy.resolve(name, 'smiles')
712
+ if smiles is None:
713
+ raise gr.Error(f"Could not find SMILES for chemical name: {name}")
714
+ except (HTTPError, URLError) as e:
715
+ raise gr.Error(f"Unable to connect to chemical database service. Please try again later or use SMILES directly. Error: {str(e)}")
716
+ except Exception as e:
717
+ raise gr.Error(f"Error resolving chemical name '{name}': {str(e)}")
718
 
719
  # Create molecule from SMILES
720
  mol = Chem.MolFromSmiles(smiles)
 
758
 
759
  return html_content
760
 
761
+ except gr.Error:
762
+ # Re-raise Gradio errors as-is
763
+ raise
764
  except Exception as e:
765
  raise gr.Error(f"Error creating 3D molecule: {str(e)}")
766
 
 
1296
  examples=[["c1ccc(CCN)cc1\nc1ccc(CCO)cc1\nc1ccc(CCC)cc1\nCCOc1ccc(CCN)cc1\nCCc1ccc(O)cc1"]],
1297
  )
1298
 
1299
+ # Reaction visualization interface
1300
+ reaction_interface = gr.Interface(
1301
+ fn=reaction_smiles_to_svg,
1302
+ inputs=gr.Textbox(
1303
+ label="Reaction SMILES",
1304
+ placeholder="CCO.O=C=O>>CC(=O)O.CO2 (Esterification reaction)",
1305
+ info="Use '>>' to separate reactants from products"
1306
+ ),
1307
+ outputs=gr.HTML(label="Reaction Visualization"),
1308
+ title="Reaction Visualizer",
1309
+ description="Visualize chemical reactions from SMILES notation.",
1310
+ api_name="reaction_visualizer",
1311
+ examples=[
1312
+ ["CCO.O=C=O>>CC(=O)O.CO2"],
1313
+ ["c1ccccc1.ClC(Cl)Cl>>c1ccccc1Cl.HCl"],
1314
+ ["CC(=O)O.[Na]>>CC(=O)O[Na]"]
1315
+ ],
1316
+ )
1317
+
1318
 
1319
  demo = gr.TabbedInterface(
1320
  [
 
1323
  properties_interface,
1324
  clustering_interface,
1325
  scaffold_interface,
1326
+ reaction_interface,
1327
  name_interface,
1328
  molecule_3d_interface,
1329
  chemiscope_interface,
 
1339
  "Property Calculator",
1340
  "Molecular Clustering",
1341
  "Scaffold Analysis",
1342
+ "Reaction Visualizer",
1343
  "Name to SMILES",
1344
  "3D Molecule Viewer",
1345
  "Chemiscope Explorer",