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()