Spaces:
Runtime error
Runtime error
Vaishnav14220
commited on
Commit
·
0a24ce6
1
Parent(s):
4946745
Add RDKit reaction SVG rendering tab
Browse files
app.py
CHANGED
|
@@ -10,6 +10,7 @@ import gradio as gr
|
|
| 10 |
import plotly.graph_objects as go
|
| 11 |
from fastapi import FastAPI, HTTPException, Query
|
| 12 |
from fastapi.middleware.cors import CORSMiddleware
|
|
|
|
| 13 |
|
| 14 |
from nist_kinetics_api import (
|
| 15 |
Category,
|
|
@@ -325,6 +326,43 @@ def _build_dataset_plot(detail: ReactionDetail) -> go.Figure | None:
|
|
| 325 |
return fig
|
| 326 |
|
| 327 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 328 |
def fetch_detail(selected_url: str, manual_url: str):
|
| 329 |
detail_url = (manual_url or "").strip() or (selected_url or "").strip()
|
| 330 |
if not detail_url:
|
|
@@ -517,6 +555,26 @@ def build_interface() -> gr.Blocks:
|
|
| 517 |
outputs=[detail_markdown, dataset_table, reaction_plot],
|
| 518 |
)
|
| 519 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 520 |
return demo
|
| 521 |
|
| 522 |
|
|
|
|
| 10 |
import plotly.graph_objects as go
|
| 11 |
from fastapi import FastAPI, HTTPException, Query
|
| 12 |
from fastapi.middleware.cors import CORSMiddleware
|
| 13 |
+
from rdkit.Chem import Draw, rdChemReactions
|
| 14 |
|
| 15 |
from nist_kinetics_api import (
|
| 16 |
Category,
|
|
|
|
| 326 |
return fig
|
| 327 |
|
| 328 |
|
| 329 |
+
def render_reaction_svg(reaction_text: str):
|
| 330 |
+
reaction_text = (reaction_text or "").strip()
|
| 331 |
+
if not reaction_text:
|
| 332 |
+
return gr.update(value=""), "⚠️ Enter a reaction SMILES/SMARTS string (e.g. CH4.O>>CO2)."
|
| 333 |
+
if ">>" not in reaction_text:
|
| 334 |
+
return gr.update(value=""), "⚠️ Reaction input must include '>>' separating reactants and products."
|
| 335 |
+
|
| 336 |
+
try:
|
| 337 |
+
reaction = rdChemReactions.ReactionFromSmarts(reaction_text, useSmiles=True)
|
| 338 |
+
except Exception as exc: # pragma: no cover - RDKit parsing issues
|
| 339 |
+
return gr.update(value=""), f"🚨 Could not parse reaction: {exc}"
|
| 340 |
+
|
| 341 |
+
if reaction is None or (reaction.GetNumReactantTemplates() == 0 and reaction.GetNumProductTemplates() == 0):
|
| 342 |
+
return gr.update(value=""), "⚠️ RDKit returned an empty reaction."
|
| 343 |
+
|
| 344 |
+
try:
|
| 345 |
+
svg = Draw.ReactionToImage(reaction, subImgSize=(220, 220), useSVG=True)
|
| 346 |
+
except Exception as exc: # pragma: no cover - RDKit drawing issues
|
| 347 |
+
return gr.update(value=""), f"🚨 Failed to render reaction: {exc}"
|
| 348 |
+
|
| 349 |
+
if isinstance(svg, tuple): # Some RDKit versions return (svg, legend)
|
| 350 |
+
svg = svg[0]
|
| 351 |
+
if hasattr(svg, "data"):
|
| 352 |
+
svg = svg.data
|
| 353 |
+
if isinstance(svg, bytes):
|
| 354 |
+
svg = svg.decode("utf-8", errors="ignore")
|
| 355 |
+
|
| 356 |
+
if not isinstance(svg, str) or "<svg" not in svg:
|
| 357 |
+
svg = f"<pre>{svg}</pre>"
|
| 358 |
+
|
| 359 |
+
status = (
|
| 360 |
+
f"Rendered reaction with {reaction.GetNumReactantTemplates()} reactant templates "
|
| 361 |
+
f"and {reaction.GetNumProductTemplates()} product templates."
|
| 362 |
+
)
|
| 363 |
+
return svg, status
|
| 364 |
+
|
| 365 |
+
|
| 366 |
def fetch_detail(selected_url: str, manual_url: str):
|
| 367 |
detail_url = (manual_url or "").strip() or (selected_url or "").strip()
|
| 368 |
if not detail_url:
|
|
|
|
| 555 |
outputs=[detail_markdown, dataset_table, reaction_plot],
|
| 556 |
)
|
| 557 |
|
| 558 |
+
with gr.Tab("Reaction SVG"):
|
| 559 |
+
gr.Markdown(
|
| 560 |
+
"Render an RDKit reaction sketch from reaction SMILES/SMARTS. "
|
| 561 |
+
"Example: `CCO.O=C=O>>CC(=O)O` or `[CH3:1].[Cl:2][C@@H](F)[Br]>>[CH3:1][C@@H](F)[Cl]`."
|
| 562 |
+
)
|
| 563 |
+
reaction_input = gr.Textbox(
|
| 564 |
+
label="Reaction SMILES/SMARTS",
|
| 565 |
+
placeholder="Reactant1.Reactant2>>Product1.Product2",
|
| 566 |
+
lines=2,
|
| 567 |
+
)
|
| 568 |
+
render_button = gr.Button("Render Reaction", variant="secondary")
|
| 569 |
+
reaction_svg = gr.HTML()
|
| 570 |
+
render_status = gr.Markdown()
|
| 571 |
+
|
| 572 |
+
render_button.click(
|
| 573 |
+
fn=render_reaction_svg,
|
| 574 |
+
inputs=reaction_input,
|
| 575 |
+
outputs=[reaction_svg, render_status],
|
| 576 |
+
)
|
| 577 |
+
|
| 578 |
return demo
|
| 579 |
|
| 580 |
|