Songyou commited on
Commit
b169fb2
·
verified ·
1 Parent(s): 5bb33b1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +25 -79
app.py CHANGED
@@ -1,31 +1,31 @@
1
  import gradio as gr
2
- from fastapi import FastAPI
3
- from starlette.staticfiles import StaticFiles
4
- import uvicorn
5
- import logging
6
- from pydantic import BaseModel
7
  import pandas as pd
8
  import time
9
 
10
- logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
11
- logger = logging.getLogger(__name__)
12
-
13
- class SmilesData(BaseModel):
14
- smiles: str
15
 
16
- app = FastAPI()
 
 
 
17
 
18
- # ketcher 目录挂载为静态资源,确保 ketcher/index.html 存在
19
- app.mount("/ketcher", StaticFiles(directory="ketcher"), name="ketcher")
 
 
 
 
 
20
 
21
- # 接收前端发送的SMILES数据的接口
22
- @app.post("/update_smiles")
23
- async def update_smiles(data: SmilesData):
24
- logger.info(f"Received SMILES from front-end: {data.smiles}")
25
- print(f"[PRINT-Backend] Received SMILES from front-end: {data.smiles}")
26
- return {"status": "ok", "received_smiles": data.smiles}
27
 
28
- # 前端嵌入的HTML和脚本
29
  KETCHER_HTML = r'''
30
  <iframe id="ifKetcher" src="/ketcher/index.html" width="100%" height="600px" style="border: 1px solid #ccc;"></iframe>
31
 
@@ -49,7 +49,6 @@ function updateGradioInput(smiles) {
49
  const input = findSmilesInput();
50
  if (input && input.value !== smiles) {
51
  input.value = smiles;
52
- // 手动触发input事件让 Gradio 更新状态
53
  input.dispatchEvent(new Event('input', { bubbles: true }));
54
  console.log("[Front-end] Updated Gradio input with SMILES:", smiles);
55
  }
@@ -63,19 +62,6 @@ async function handleKetcherChange() {
63
  if (smiles !== lastSmiles) {
64
  lastSmiles = smiles;
65
  updateGradioInput(smiles);
66
-
67
- // 将SMILES发送给后端 (可以保留,但可能不是核心需求)
68
- console.log("[Front-end] Sending SMILES to backend...");
69
- fetch('/update_smiles', {
70
- method: 'POST',
71
- headers: {'Content-Type': 'application/json'},
72
- body: JSON.stringify({smiles: smiles})
73
- })
74
- .then(res => res.json())
75
- .then(data => {
76
- console.log("[Front-end] Backend response:", data);
77
- })
78
- .catch(err => console.error("[Front-end] Error sending SMILES to backend:", err));
79
  }
80
  } catch (err) {
81
  console.error("[Front-end] Error getting SMILES from Ketcher:", err);
@@ -101,24 +87,16 @@ function initKetcher() {
101
  ketcher = ketcherWindow.ketcher;
102
  console.log("[Front-end] Ketcher instance acquired:", ketcher);
103
 
104
- // 设置初始分子
105
  ketcher.setMolecule('C').then(() => {
106
  console.log("[Front-end] Initial molecule set to 'C'.");
107
  });
108
 
109
  const editor = ketcher.editor;
110
- console.log("[Front-end] Editor object:", editor);
111
-
112
- // 尝试绑定变化事件
113
- let eventBound = false;
114
  if (editor && typeof editor.subscribe === 'function') {
115
  console.log("[Front-end] Using editor.subscribe('change', ...)");
116
  editor.subscribe('change', handleKetcherChange);
117
- eventBound = true;
118
- }
119
-
120
- if (!eventBound) {
121
- console.error("[Front-end] No suitable event binding found. Check Ketcher version and event API.");
122
  }
123
  }
124
 
@@ -129,30 +107,6 @@ document.getElementById('ifKetcher').addEventListener('load', () => {
129
  </script>
130
  '''
131
 
132
- # --- 模拟后端功能 (来自第二个版本) ---
133
- def smiles_to_structure(smiles):
134
- """Dummy function"""
135
- time.sleep(1)
136
- return f"Structure Generated from: {smiles}"
137
-
138
- def fragment_molecule(smiles):
139
- """Dummy function"""
140
- time.sleep(2)
141
- return "Fragment1", "Fragment2", "1-2"
142
-
143
- def generate_analogs(main_cls, minor_cls, number, delta_value):
144
- """Dummy function"""
145
- time.sleep(3)
146
- return [
147
- {"SMILE": "c1cccc1", "MolWt": 100, "TPSA": 20, "SLogP": 1, "SA": 30, "QED": 0.8},
148
- {"SMILE": "c1ccccc1", "MolWt": 105, "TPSA": 25, "SLogP": 1.2, "SA": 32, "QED": 0.9},
149
- ]
150
-
151
- def update_output_table(data):
152
- df = pd.DataFrame(data)
153
- return df
154
-
155
- # --- Gradio 界面 ---
156
  def create_combined_interface():
157
  with gr.Blocks() as demo:
158
  gr.Markdown("# Fragment Optimization Tools with Ketcher")
@@ -171,10 +125,7 @@ def create_combined_interface():
171
  elem_id="combined_smiles_input"
172
  )
173
  with gr.Row():
174
- # 可以保留一个按钮来触发某些操作,例如手动同步
175
  get_ketcher_smiles_btn = gr.Button("Get SMILES from Ketcher")
176
- # 示例:将当前输入框的 SMILES 设置到 Ketcher (需要额外的前端 JavaScript)
177
- # set_ketcher_smiles_btn = gr.Button("Set SMILES to Ketcher")
178
  fragment_btn = gr.Button("Fragmentize Molecule")
179
 
180
  with gr.Group():
@@ -204,7 +155,6 @@ def create_combined_interface():
204
  download_selected_btn = gr.Button("Download Selected")
205
 
206
  # --- 事件处理 ---
207
- # 当点击按钮时,手动从 Ketcher 获取 SMILES 并更新输入框
208
  get_ketcher_smiles_btn.click(
209
  fn=None,
210
  inputs=None,
@@ -222,12 +172,8 @@ def create_combined_interface():
222
  inputs=[main_cls_dropdown, minor_cls_dropdown, number_input, delta_value_slider],
223
  outputs=output_table)
224
 
225
- # TODO: 添加下载功能的回调
226
-
227
  return demo
228
 
229
- combined_demo = create_combined_interface()
230
- app = gr.mount_gradio_app(app, combined_demo, path="/")
231
-
232
- if __name__ == "__main__":
233
- uvicorn.run(app, host="127.0.0.1", port=7860)
 
1
  import gradio as gr
 
 
 
 
 
2
  import pandas as pd
3
  import time
4
 
5
+ # --- 模拟后端功能 (来自第二个版本) ---
6
+ def smiles_to_structure(smiles):
7
+ """Dummy function"""
8
+ time.sleep(1)
9
+ return f"Structure Generated from: {smiles}"
10
 
11
+ def fragment_molecule(smiles):
12
+ """Dummy function"""
13
+ time.sleep(2)
14
+ return "Fragment1", "Fragment2", "1-2"
15
 
16
+ def generate_analogs(main_cls, minor_cls, number, delta_value):
17
+ """Dummy function"""
18
+ time.sleep(3)
19
+ return [
20
+ {"SMILE": "c1cccc1", "MolWt": 100, "TPSA": 20, "SLogP": 1, "SA": 30, "QED": 0.8},
21
+ {"SMILE": "c1ccccc1", "MolWt": 105, "TPSA": 25, "SLogP": 1.2, "SA": 32, "QED": 0.9},
22
+ ]
23
 
24
+ def update_output_table(data):
25
+ df = pd.DataFrame(data)
26
+ return df
 
 
 
27
 
28
+ # --- Gradio 界面 ---
29
  KETCHER_HTML = r'''
30
  <iframe id="ifKetcher" src="/ketcher/index.html" width="100%" height="600px" style="border: 1px solid #ccc;"></iframe>
31
 
 
49
  const input = findSmilesInput();
50
  if (input && input.value !== smiles) {
51
  input.value = smiles;
 
52
  input.dispatchEvent(new Event('input', { bubbles: true }));
53
  console.log("[Front-end] Updated Gradio input with SMILES:", smiles);
54
  }
 
62
  if (smiles !== lastSmiles) {
63
  lastSmiles = smiles;
64
  updateGradioInput(smiles);
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  }
66
  } catch (err) {
67
  console.error("[Front-end] Error getting SMILES from Ketcher:", err);
 
87
  ketcher = ketcherWindow.ketcher;
88
  console.log("[Front-end] Ketcher instance acquired:", ketcher);
89
 
 
90
  ketcher.setMolecule('C').then(() => {
91
  console.log("[Front-end] Initial molecule set to 'C'.");
92
  });
93
 
94
  const editor = ketcher.editor;
 
 
 
 
95
  if (editor && typeof editor.subscribe === 'function') {
96
  console.log("[Front-end] Using editor.subscribe('change', ...)");
97
  editor.subscribe('change', handleKetcherChange);
98
+ } else {
99
+ console.error("[Front-end] No suitable event binding found.");
 
 
 
100
  }
101
  }
102
 
 
107
  </script>
108
  '''
109
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  def create_combined_interface():
111
  with gr.Blocks() as demo:
112
  gr.Markdown("# Fragment Optimization Tools with Ketcher")
 
125
  elem_id="combined_smiles_input"
126
  )
127
  with gr.Row():
 
128
  get_ketcher_smiles_btn = gr.Button("Get SMILES from Ketcher")
 
 
129
  fragment_btn = gr.Button("Fragmentize Molecule")
130
 
131
  with gr.Group():
 
155
  download_selected_btn = gr.Button("Download Selected")
156
 
157
  # --- 事件处理 ---
 
158
  get_ketcher_smiles_btn.click(
159
  fn=None,
160
  inputs=None,
 
172
  inputs=[main_cls_dropdown, minor_cls_dropdown, number_input, delta_value_slider],
173
  outputs=output_table)
174
 
 
 
175
  return demo
176
 
177
+ # 创建 Gradio 界面并启动
178
+ demo = create_combined_interface()
179
+ demo.launch()