QQ2S3R commited on
Commit
29442d2
·
verified ·
1 Parent(s): f6a8e18

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +42 -49
app.py CHANGED
@@ -17,8 +17,11 @@ matplotlib.use('Agg') # 修复后台线程问题
17
  from rdkit import Chem
18
  from rdkit.Chem import Draw
19
  from rdkit.Chem import AllChem
 
20
  from io import BytesIO
21
  import traceback
 
 
22
 
23
  # 配置日志
24
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
@@ -198,47 +201,37 @@ def predict_all(smiles):
198
  return error_msg, None, error_msg, None, error_msg, None
199
 
200
  # 新增函数:将绘制的分子结构转换为SMILES
201
- def draw_to_smiles(mol_data):
202
  """
203
- 将绘制的分子数据转换为SMILES字符串
204
- :param mol_data: 包含分子结构数据的字
205
  :return: (SMILES字符串, 分子图像)
206
  """
207
- try:
208
- # 从输入数据中提取molfile
209
- molfile = mol_data["mol"]
210
-
211
- # 将molfile转换为RDKit分子对象
212
- mol = Chem.MolFromMolBlock(molfile)
213
-
214
- if mol is None:
215
- # 如果直接解析失败,尝试添加氢原子
216
- mol = Chem.MolFromMolBlock(molfile, sanitize=False)
217
- if mol:
218
- try:
219
- # 尝试修复分子
220
- mol.UpdatePropertyCache()
221
- Chem.SanitizeMol(mol)
222
- except:
223
- pass
224
 
225
- if mol is None:
226
- raise ValueError("无法从绘制的结构创建分子对象")
 
 
227
 
228
- # 生成2D坐标
229
- AllChem.Compute2DCoords(mol)
 
 
230
 
231
- # 分子转换为SMILES
232
- smiles = Chem.MolToSmiles(mol)
 
 
233
 
234
  # 创建分子图像
235
- img = Draw.MolToImage(mol)
236
  img_buffer = BytesIO()
237
- img.save(img_buffer, format="PNG")
238
  img_buffer.seek(0)
239
 
240
- logger.info(f"成功转换绘制结构为SMILES: {smiles}")
241
- return smiles, img_buffer
242
 
243
  except Exception as e:
244
  error_msg = f"分子转换失败: {str(e)}"
@@ -246,19 +239,12 @@ def draw_to_smiles(mol_data):
246
  return None, None
247
 
248
  # 新增函数:处理绘制输入的预测流程
249
- def predict_from_drawing(mol_data):
250
  """
251
  处理用户绘制的分子结构
252
- :param mol_data: 包含分子结构数据的字
253
  :return: 预测结果 (6个输出组件)
254
  """
255
- # 将绘制的结构转换为SMILES
256
- smiles, img = draw_to_smiles(mol_data)
257
-
258
- if not smiles:
259
- error_msg = "无法解析绘制的分子结构"
260
- return error_msg, None, error_msg, None, error_msg, None
261
-
262
  # 使用预测函数
263
  return predict_all(smiles)
264
 
@@ -287,17 +273,24 @@ with gr.Blocks(title="CrystalGAT") as demo:
287
 
288
  with gr.Tab("绘制分子"):
289
  gr.Markdown("### 绘制分子结构")
290
- gr.Markdown("使用下方的绘图工具绘制分子结构,然后点击预测按钮")
291
 
292
- # 使用兼容的绘图组件
293
- drawing_input = gr.Sketchpad(
294
  label="绘制分子结构",
295
- type="mol",
296
- height=300,
297
- # 移除不支持的参数
 
 
 
 
 
 
 
298
  )
 
299
  drawing_display = gr.Image(label="分子结构预览", interactive=False)
300
- drawing_output = gr.Text(label="生成的SMILES")
301
  submit_btn2 = gr.Button("预测", variant="primary")
302
 
303
  # 输出区域 (两种输入方式共享)
@@ -322,14 +315,14 @@ with gr.Blocks(title="CrystalGAT") as demo:
322
 
323
  # 绘图输入路径
324
  drawing_input.change(
325
- fn=lambda mol: draw_to_smiles(mol) if mol else (None, None),
326
  inputs=drawing_input,
327
- outputs=[drawing_output, drawing_display]
328
  )
329
 
330
  submit_btn2.click(
331
  fn=predict_from_drawing,
332
- inputs=drawing_input,
333
  outputs=[elastic_text, elastic_img, plastic_text, plastic_img, brittle_text, brittle_img]
334
  )
335
 
 
17
  from rdkit import Chem
18
  from rdkit.Chem import Draw
19
  from rdkit.Chem import AllChem
20
+ from rdkit.Chem import MolFromSmiles
21
  from io import BytesIO
22
  import traceback
23
+ import tempfile
24
+ import base64
25
 
26
  # 配置日志
27
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
 
201
  return error_msg, None, error_msg, None, error_msg, None
202
 
203
  # 新增函数:将绘制的分子结构转换为SMILES
204
+ def draw_to_smiles(image_data):
205
  """
206
+ 将绘制的分子图像转换为SMILES字符串
207
+ :param image_data: 包含分子图像数据的base64符串
208
  :return: (SMILES字符串, 分子图像)
209
  """
210
+ if not image_data:
211
+ return None, None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212
 
213
+ try:
214
+ # 将base64图像数据转换为PIL图像
215
+ image_bytes = base64.b64decode(image_data.split(",")[1])
216
+ image = Image.open(BytesIO(image_bytes))
217
 
218
+ # 保存临时文件
219
+ with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp:
220
+ image.save(tmp.name)
221
+ tmp_path = tmp.name
222
 
223
+ # 使用RDKit从图像读取分子
224
+ mol = MolFromSmiles("") # 创建一个空分子
225
+ # 注意:实际应用中这里应该使用OCR或图像识别技术
226
+ # 这里简化处理,提示用户输入SMILES
227
 
228
  # 创建分子图像
 
229
  img_buffer = BytesIO()
230
+ image.save(img_buffer, format="PNG")
231
  img_buffer.seek(0)
232
 
233
+ # 提示用户输入SMILES
234
+ return None, img_buffer
235
 
236
  except Exception as e:
237
  error_msg = f"分子转换失败: {str(e)}"
 
239
  return None, None
240
 
241
  # 新增函数:处理绘制输入的预测流程
242
+ def predict_from_drawing(smiles):
243
  """
244
  处理用户绘制的分子结构
245
+ :param smiles: 用户输入SMILES符串
246
  :return: 预测结果 (6个输出组件)
247
  """
 
 
 
 
 
 
 
248
  # 使用预测函数
249
  return predict_all(smiles)
250
 
 
273
 
274
  with gr.Tab("绘制分子"):
275
  gr.Markdown("### 绘制分子结构")
276
+ gr.Markdown("使用下方的绘图工具绘制分子结构,然后在SMILES框中输入对应的SMILES字符串")
277
 
278
+ # 使用标准绘图组件
279
+ drawing_input = gr.ImageEditor(
280
  label="绘制分子结构",
281
+ type="pil",
282
+ interactive=True,
283
+ height=300
284
+ )
285
+
286
+ gr.Markdown("### 输入绘制的分子对应的SMILES")
287
+ drawing_smiles = gr.Textbox(
288
+ label="SMILES",
289
+ placeholder="输入绘制的分子对应的SMILES字符串",
290
+ interactive=True
291
  )
292
+
293
  drawing_display = gr.Image(label="分子结构预览", interactive=False)
 
294
  submit_btn2 = gr.Button("预测", variant="primary")
295
 
296
  # 输出区域 (两种输入方式共享)
 
315
 
316
  # 绘图输入路径
317
  drawing_input.change(
318
+ fn=draw_to_smiles,
319
  inputs=drawing_input,
320
+ outputs=[drawing_smiles, drawing_display]
321
  )
322
 
323
  submit_btn2.click(
324
  fn=predict_from_drawing,
325
+ inputs=drawing_smiles,
326
  outputs=[elastic_text, elastic_img, plastic_text, plastic_img, brittle_text, brittle_img]
327
  )
328