如何将“IPython.core.display.SVG”另存为PNG文件?

问题描述 投票:0回答:2

我正在尝试在 Jupyter Notebook 环境中将数据类型为“IPython.core.display.SVG”的变量保存为 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
  • Python 3.6
  • RDKit版本2020.09.1

非常感谢任何帮助。

svg jupyter-notebook ipython png rdkit
2个回答
2
投票

与其使用 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")

0
投票

问题是:

我正在尝试在 Jupyter Notebook 环境中将数据类型为“IPython.core.display.SVG”的变量保存为 PNG 文件。

我的尝试,猜测在任何地方都有效(??);

首先我需要创建一个

IPython.core.display.SVG
对象,然后从该对象中提取 data (str ??) 并将其编码以从
svg2png
库提供给
cairosvg
,见下文:


from io import BytesIO

from cairosvg import svg2png

from PIL import Image

svg_code = """
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
        <circle cx="12" cy="12" r="10"/>
        <line x1="12" y1="8" x2="12" y2="12"/>
        <line x1="12" y1="16" x2="12" y2="16"/>
    </svg>
    """
    
from IPython.core.display import SVG

d2g = SVG(svg_code)


print('d2g : ', d2g)

print('type(d2g) : ', type(d2g))    

print('d2g.data : ', d2g.data)

print('type(d2g.data) : ', type(d2g.data))    
    
svg_data = BytesIO(d2g.data.encode())
    
# with open('output.svg', 'w') as f:
            
#     f.write(svg_data)
        
png = svg2png(bytestring=svg_data.read())

pil_img = Image.open(BytesIO(png)).convert('RGBA')
pil_img.save('pil.png')
    
print(type(pil_img))  

pil_img.show()

输出:

d2g :  <IPython.core.display.SVG object>
type(d2g) :  <class 'IPython.core.display.SVG'>
d2g.data :  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
        <circle cx="12" cy="12" r="10"/>
        <line x1="12" y1="8" x2="12" y2="12"/>
        <line x1="12" y1="16" x2="12" y2="16"/>
    </svg>
type(d2g.data) :  <class 'str'>
<class 'PIL.Image.Image'>

图像输出:

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.