svg - 如何将“IPython.core.display.SVG”保存为 PNG 文件?
问题描述
我正在尝试将数据类型为“IPython.core.display.SVG”的变量保存为 Jupyter Notebook 环境中的 PNG 文件。
首先我试过:
with open('./file.png','wb+') as outfile:
outfile.write(my_svg.data)
我得到了错误:
TypeError: a bytes-like object is required, not 'str'
接下来,我尝试了:
with open('./file.png','wb+') as outfile:
outfile.write(my_svg.data.encode('utf-8'))
但是,我无法打开“file.png”。操作系统报错:
The file “file.png” could not be opened. It may be damaged or use a file format that Preview doesn’t recognize.
我可以使用“svg”扩展名保存“my_svg”,如下所示:
with open('./file.svg','wb+') as outfile:
outfile.write(my_svg.data.encode('utf-8'))
但是,当我想通过以下方式将“file.svg”转换为“file.png”时:
import cairosvg
cairosvg.svg2png(url="./file.svg", write_to="./file.png")
我得到错误:
ValueError: unknown locale: UTF-8
这就是我在 Jupyter Notebook 中获得“IPython.core.display.SVG”数据类型的方式:
from rdkit import Chem
from rdkit.Chem.Draw import rdMolDraw2D
from IPython.display import SVG
smile_1 = 'C(C(N)=O)c(c)c'
smile_2 = 'o(cn)c(c)c'
m1 = Chem.MolFromSmiles(smile_1,sanitize=False)
Chem.SanitizeMol(m1, sanitizeOps=(Chem.SanitizeFlags.SANITIZE_ALL^Chem.SanitizeFlags.SANITIZE_KEKULIZE^Chem.SanitizeFlags.SANITIZE_SETAROMATICITY))
m2 = Chem.MolFromSmiles(smile_2,sanitize=False)
Chem.SanitizeMol(m2, sanitizeOps=(Chem.SanitizeFlags.SANITIZE_ALL^Chem.SanitizeFlags.SANITIZE_KEKULIZE^Chem.SanitizeFlags.SANITIZE_SETAROMATICITY))
mols = [m1, m2]
legends = ["smile_1", "smile_2"]
molsPerRow=2
subImgSize=(200, 200)
nRows = len(mols) // molsPerRow
if len(mols) % molsPerRow:
nRows += 1
fullSize = (molsPerRow * subImgSize[0], nRows * subImgSize[1])
d2d = rdMolDraw2D.MolDraw2DSVG(fullSize[0], fullSize[1], subImgSize[0], subImgSize[1])
d2d.drawOptions().prepareMolsBeforeDrawing=False
d2d.DrawMolecules(list(mols), legends=legends)
d2d.FinishDrawing()
SVG(d2d.GetDrawingText())
环境:
- macOS 11.2.3
- 蟒蛇3.6
- RDKit 版本 2020.09.1
任何帮助是极大的赞赏。
解决方案
与其用 rdkit 创建 SVG 并尝试将其转换为 PNG,不如直接创建一个 PNG?
from rdkit.Chem import Draw
from rdkit import Chem
# create rdkit mol
smile = 'CCCC'
mol = Chem.MolFromSmiles(smile)
# create png
d2d = Draw.MolDraw2DCairo(200, 200)
d2d.DrawMolecule(mol)
d2d.FinishDrawing()
png_data = d2d.GetDrawingText()
# save png to file
with open('mol_image.png', 'wb') as png_file:
png_file.write(png_data)
我不确定为什么 MolDraw2DCairo 不适合你,但使用你提到的包(cairosvg)你可以很容易地扩展你的代码示例:
# extra imports
import cairosvg
import tempfile
# replace molecule drawing part
d2d = rdMolDraw2D.MolDraw2DSVG(fullSize[0], fullSize[1], subImgSize[0], subImgSize[1])
d2d.drawOptions().prepareMolsBeforeDrawing=False
d2d.DrawMolecules(list(mols), legends=legends)
d2d.FinishDrawing()
svg_text = d2d.GetDrawingText()
# save to png file
with tempfile.NamedTemporaryFile(delete=True) as tmp:
tmp.write(svg_text.encode())
tmp.flush()
cairosvg.svg2png(url=tmp.name, write_to="./mol_img.png")
推荐阅读
- javascript - 根据 Flow 中的对象值定义联合类型
- python-3.x - Matplotlib“补丁”之类的功能
- excel - Excel VBA 获取唯一值
- terminal - Gnuplot 图中的一般错位
- angular - 组件之间的Angular 2数据绑定
- javascript - 如何用纯javascript编写jquery的parent().parent().parent()
- c# - 在 webmethod 上的 Task.Run() 内锁定不工作 c#?
- vba - 使用替换的公式的自定义函数
- apache-spark - 按组触发 topN 值
- python - 如何跟踪 cx_Oracle 如何尝试连接到数据库?