import gradio as gr
import pandas as pd
import time
# --- 模拟后端功能 (来自第二个版本) ---
def smiles_to_structure(smiles):
"""Dummy function"""
time.sleep(1)
return f"Structure Generated from: {smiles}"
def fragment_molecule(smiles):
"""Dummy function"""
time.sleep(2)
return "Fragment1", "Fragment2", "1-2"
def generate_analogs(main_cls, minor_cls, number, delta_value):
"""Dummy function"""
time.sleep(3)
return [
{"SMILE": "c1cccc1", "MolWt": 100, "TPSA": 20, "SLogP": 1, "SA": 30, "QED": 0.8},
{"SMILE": "c1ccccc1", "MolWt": 105, "TPSA": 25, "SLogP": 1.2, "SA": 32, "QED": 0.9},
]
def update_output_table(data):
df = pd.DataFrame(data)
return df
# --- Gradio 界面 ---
KETCHER_HTML = r'''
'''
def create_combined_interface():
with gr.Blocks() as demo:
gr.Markdown("# Fragment Optimization Tools with Ketcher")
with gr.Row():
with gr.Column(scale=2):
gr.HTML(KETCHER_HTML) # 嵌入 Ketcher,仅加载一次
with gr.Column(scale=1):
gr.Markdown("### Input SMILES (From Ketcher)")
combined_smiles_input = gr.Textbox(
label="",
value="C",
placeholder="SMILES from Ketcher will appear here",
elem_id="combined_smiles_input"
)
get_ketcher_smiles_btn = gr.Button("Get SMILES from Ketcher")
fragment_btn = gr.Button("Fragmentize Molecule")
constant_frag_input = gr.Textbox(label="Constant Fragment", placeholder="SMILES of constant fragment")
variable_frag_input = gr.Textbox(label="Variable Fragment", placeholder="SMILES of variable fragment")
attach_order_input = gr.Textbox(label="Attachment Order", placeholder="Attachment Order of SMILES")
main_cls_dropdown = gr.Dropdown(label="Main Cls", choices=["None", "Cl", "Br"])
minor_cls_dropdown = gr.Dropdown(label="Minor Cls", choices=["None", "Cl", "Br"])
number_input = gr.Number(label="Number", value=5, step=1)
delta_value_slider = gr.Slider(minimum=0, maximum=10, step=1, label="Delta Value", interactive=True)
generate_analogs_btn = gr.Button("Generate")
output_table = gr.Dataframe(headers=["SMILE", "MolWt", "TPSA", "SLogP", "SA", "QED"])
# --- 事件处理 ---
get_ketcher_smiles_btn.click(
fn=None,
inputs=None,
outputs=combined_smiles_input,
js="async () => { const iframe = document.getElementById('ifKetcher'); if(iframe && iframe.contentWindow && iframe.contentWindow.ketcher) { const smiles = await iframe.contentWindow.ketcher.getSmiles(); return smiles; } else { console.error('Ketcher not ready'); return ''; } }"
)
fragment_btn.click(fragment_molecule, inputs=combined_smiles_input, outputs=[constant_frag_input, variable_frag_input, attach_order_input])
def update_table_with_analogs(main_cls, minor_cls, number, delta_value):
analogs_data = generate_analogs(main_cls, minor_cls, number, delta_value)
return update_output_table(analogs_data)
generate_analogs_btn.click(update_table_with_analogs,
inputs=[main_cls_dropdown, minor_cls_dropdown, number_input, delta_value_slider],
outputs=output_table)
return demo
# 创建 Gradio 界面并启动
demo = create_combined_interface()
demo.launch()