RDKit 图像 MolToImage 缩放键宽度和元素标签对于不同的图像尺寸不一致?

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

我注意到,当我在 RDKit 中从分子创建图像时,

size
参数会导致键宽和元素标签的缩放不一致。尺寸越大,线条越细,元素标签越小。

我通过使用

MolToImage
以逐渐变大的尺寸为同一分子生成图像来进行测试。我将这些图像重新缩放为
size=(600,600)
,然后将它们连接成 GIF。这就是结果。

Resulting GIF

这是我的代码

from glob import glob
from rdkit import Chem
from rdkit.Chem import Draw
from PIL import Image,ImageDraw,ImageFont


def make_frames_from_smi(smi):

    for i in range(10):
        s = (i+3)*100
        mol = Chem.MolFromSmiles(smi)
        img = Draw.MolToImage(mol,size=(s,s))
        img = img.resize((600,600))
        draw = ImageDraw.Draw(img)

        text = '%d: Initial Size: (%d,%d)'%(i+1,s,s)

        font_size = 40
        font = ImageFont.truetype("arial.ttf", font_size)  # Use your desired font


        # Calculate text position
        image_width, image_height = img.size
        text_x = (image_width - (bbox[2] - bbox[0])) // 2
        text_y = 20  # Adjust the vertical position as needed

        draw.text((text_x, text_y), text, font=font, fill='black')
        img.save('%03dtest.png'%i)


def make_gif_from_frames(paths):

    frames_paths = glob(paths)
    frames = [Image.open(imgp) for imgp in frames_paths]

    frames[0].save("mols.gif", format="GIF", append_images=frames, save_all=True, duration=500, loop=False)



# make RDKit mol obj.
smi = 'CN(C)CC1CCCCC1(C2=CC(=CC=C2)OC)O'
make_frames_from_smi(smi)
make_gif_from_frames('*.png')

这是预期的行为吗?对于一定的像素绝对值,键合宽度是否保持恒定?无论像素的宽度/高度如何,如何生成比例一致的这些图像?

python image python-imaging-library rdkit
1个回答
0
投票

好的找到了,我希望有两个解决方案???

第一个,使用

Draw.rdMolDraw2D.MolDraw2DCairo

from glob import glob
from rdkit import Chem
from rdkit.Chem import Draw
from PIL import Image


from io import BytesIO

def make_frames_from_smi(smi):

    mol = Chem.MolFromSmiles(smi)

    for i in range(10):
        s = (i+3)*100
        mol = Chem.MolFromSmiles(smi)
        
        d = Draw.rdMolDraw2D.MolDraw2DCairo(s,s)
        
        dopts = d.drawOptions()
        
        # dopts.maxFontSize=40
        # dopts.minFontSize=40
        
        dopts.maxFontSize=int(0.13*s)
        dopts.minFontSize=int(0.13*s)
    
        
        d.DrawMolecule(mol)
        
        d.FinishDrawing()

        
        img = d.GetDrawingText()
        
        img_b = BytesIO()
    
        img_b.write(img)
        
        
        pil_img = Image.open(img_b).resize((600,600))
        
        pil_img.save('%03dtest.png'%i)
        
        


def make_gif_from_frames(paths):

    frames_paths = glob(paths)
    frames = [Image.open(imgp) for imgp in frames_paths]

    frames[0].save("mols.gif", format="GIF", append_images=frames, save_all=True, duration=500, loop=False)


smi = 'CN(C)CC1CCCCC1(C2=CC(=CC=C2)OC)O'
make_frames_from_smi(smi)
make_gif_from_frames('*.png')

结果:

enter image description here

或者使用 SVG,

Draw.rdMolDraw2D.MolDraw2DSVG
,我更喜欢它作为图片格式:

import rdkit

print('\n-------------------------------')
print('\n rdkit Version : ', rdkit.__version__)
print('\n-------------------------------')

from glob import glob
from rdkit import Chem
from rdkit.Chem import Draw
from PIL import Image,ImageDraw,ImageFont

from io import BytesIO
from cairosvg import svg2png

from moviepy.editor import ImageClip, concatenate_videoclips

def make_frames_from_smi(smi):

    mol = Chem.MolFromSmiles(smi)

    drawer= Draw.rdMolDraw2D.MolDraw2DSVG(600,600)
    
    dopts = drawer.drawOptions()
    
    for i in dir(dopts) :
        
        print(i)
        
    dopts.minFontSize = -1
    dopts.maxFontSize = -1
        
    # dopts.minFontSize = 80
    # dopts.maxFontSize = 80
    
    print('drawer.FontSize : ', drawer.FontSize())
          
    # dopts.annotationFontScale = 0.5
    
    dopts.addAtomIndices = True
        
    drawer.DrawMolecule(mol)

        
    drawer.FinishDrawing()

    svg_data = drawer.GetDrawingText()


        
    with open('dtest.svg' , 'w') as handler:
            
            handler.write(svg_data)
    
    for i in range(10):
        s = (i+3)*100
        
        png = svg2png(bytestring=svg_data)

        img = Image.open(BytesIO(png)).convert('RGBA').resize((s,s))

        img.save('%03dtest.png'%i)


def make_gif_from_frames(paths):
    
    input_png_list = glob(paths)
    input_png_list.sort()
    
    
    clips = [ImageClip(i).set_duration(1)
                  for i in input_png_list]
    concat_clip = concatenate_videoclips(clips, method="compose")
    concat_clip.write_gif("test.gif", fps=2)    
    

smi = 'CN(C)CC1CCCCC1(C2=CC(=CC=C2)OC)O'
make_frames_from_smi(smi)
make_gif_from_frames('*.png')

结果:

enter image description here

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