如何使用Python在RDKit中使用MolsToGridImage更改突出显示颜色?

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

化学信息学 RDKit 工具以 RDKit Cookbook 为特色,其中包含适用于一系列应用的示例代码。其中之一是突出显示 2 个分子之间的差异,这里使用 fMCS 来映射相似性,然后标记那些不共享的残基。 这个例子效果很好,代码是这里

我需要更改突出显示颜色,但无法使其工作。根据上面的代码链接,到目前为止我已经尝试过:

from rdkit import Chem
from rdkit.Chem import Draw
from rdkit.Chem.Draw import rdMolDraw2D
from rdkit.Chem.Draw import IPythonConsole
from rdkit.Chem import rdFMCS
from rdkit.Chem.Draw import rdDepictor
rdDepictor.SetPreferCoordGen(True)
IPythonConsole.drawOptions.minFontSize=20
IPythonConsole.drawOptions.setHighlightColour=(0,1,0)
from collections import defaultdict

这完全没有效果,图片是用默认高亮绘制的。

d2g = Draw.MolsToGridImage([mol1, mol2]) 
opts = d2g.drawOptions()
opts.setHighlightColour = (0,1,0)
d2g([mol1, mol2],highlightAtomLists=[target_atm1, target_atm2])

这会引发错误

AttributeError:“图像”对象没有属性“drawOptions”

然后我让它与这个一起工作:

from rdkit import Chem
from rdkit.Chem import Draw
from rdkit.Chem.Draw import rdMolDraw2D
from rdkit.Chem.Draw import IPythonConsole
from rdkit.Chem import rdFMCS
from rdkit.Chem.Draw import rdDepictor
rdDepictor.SetPreferCoordGen(True)
IPythonConsole.drawOptions.minFontSize=20
from collections import defaultdict

mol1 = Chem.MolFromSmiles('FC1=CC=C2C(=C1)C=NN2')
mol2 = Chem.MolFromSmiles('CCC1=C2NN=CC2=CC(Cl)=C1')

from PIL import Image
from io import BytesIO
def show_mol(d2d,mol,legend='',highlightAtoms=[]):
    d2d.DrawMolecule(mol,legend=legend, highlightAtoms=highlightAtoms)
    d2d.FinishDrawing()
    bio = BytesIO(d2d.GetDrawingText())
    return Image.open(bio)
def show_images(imgs,buffer=5):
    height = 0
    width = 0
    for img in imgs:
        height = max(height,img.height)
        width += img.width
    width += buffer*(len(imgs)-1)
    res = Image.new("RGBA",(width,height))
    x = 0
    for img in imgs:
        res.paste(img,(x,0))
        x += img.width + buffer
    return res

mcs = rdFMCS.FindMCS([mol1,mol2])
mcs_mol = Chem.MolFromSmarts(mcs.smartsString)
match1 = mol1.GetSubstructMatch(mcs_mol)
target_atm1 = []
for atom in mol1.GetAtoms():
        if atom.GetIdx() not in match1:
            target_atm1.append(atom.GetIdx())
match2 = mol2.GetSubstructMatch(mcs_mol)
target_atm2 = []
for atom in mol2.GetAtoms():
        if atom.GetIdx() not in match2:
            target_atm2.append(atom.GetIdx())

img1 = []
d2dx = Draw.MolDraw2DCairo(350,300)
doptsx = d2dx.drawOptions()
doptsx.setHighlightColour((1,0.84,0,.5))
img1.append(show_mol(d2dx,mol1,highlightAtoms=target_atm1))
d2dx = Draw.MolDraw2DCairo(350,300)
doptsx = d2dx.drawOptions()
doptsx.setHighlightColour((1,0.84,0,.5))
img1.append(show_mol(d2dx,mol2, highlightAtoms=target_atm2))
pic = show_images(img1)
pic.save('hallo.png')
pic

问题是,1)我需要 svg 输出,2)如果分子具有不同的大小或使用备用 SMILE 配置,则只有 MolsToGrid 将它们正确放置在相同的子面板边界内。所以我需要使用 MolsToGrid 来获取科学出版质量的图像。

我是一个在 Windows 11 PC 上使用 jupyter lab 的完整 Python n00b。

Python 3.8.18(默认,2023 年 9 月 11 日,13:39:12)[MSC v.1916 64 位 (AMD64)] :: Anaconda, Inc. 在 win32 上

我非常感谢任何帮助,提前致谢! :)

python rdkit
1个回答
0
投票

无法弄清楚如何在

HighlightAtomColors
 中设置 
MolToGridImage

采取:

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

from rdkit import Chem
from rdkit.Chem import Draw
from rdkit.Chem import rdFMCS

from io import BytesIO, StringIO

smi1 = 'FC1=CC=C2C(=C1)C=NN2'
smi2 = 'CCC1=C2NN=CC2=CC(Cl)=C1'

print(smi1)
print(smi2)

mol1 = Chem.MolFromSmiles(smi1)
mol2 = Chem.MolFromSmiles(smi2)

smi_mol1 = Chem.MolToSmiles(mol1)
smi_mol2 = Chem.MolToSmiles(mol2)

print(smi_mol1)
print(smi_mol2)


def show_mol(d2d,mol,legend='',highlightAtoms=[]):
    d2d.DrawMolecule(mol,legend=legend, highlightAtoms=highlightAtoms)
    d2d.FinishDrawing()
   
    svg = d2d.GetDrawingText()
    img = BytesIO(svg.encode())
    
    # print(img.read())
    # img.seek(0)
    
    return img  



mcs = rdFMCS.FindMCS([mol1,mol2])
mcs_mol = Chem.MolFromSmarts(mcs.smartsString)
match1 = mol1.GetSubstructMatch(mcs_mol)
target_atm1 = []
for atom in mol1.GetAtoms():
        if atom.GetIdx() not in match1:
            target_atm1.append(atom.GetIdx())
match2 = mol2.GetSubstructMatch(mcs_mol)
target_atm2 = []
for atom in mol2.GetAtoms():
        if atom.GetIdx() not in match2:
            target_atm2.append(atom.GetIdx())

img1 = []
d2dx = Draw.MolDraw2DSVG(350,300)
doptsx = d2dx.drawOptions()
doptsx.setHighlightColour((1,0.84,0,.5))
doptsx.bgColor=None
img1.append(show_mol(d2dx,mol1,highlightAtoms=target_atm1))

d2dx = Draw.MolDraw2DSVG(350,300)
doptsx = d2dx.drawOptions()
doptsx.setHighlightColour((0,0.84,0,.5))
doptsx.bgColor=None
img1.append(show_mol(d2dx,mol2, highlightAtoms=target_atm2))




#### https://stackoverflow.com/questions/61800296/python-merging-2-svg-elelments-into-one-svg-element
import io

from svglib.svglib import svg2rlg

from reportlab.graphics.shapes import Drawing
from reportlab.graphics.renderSVG import SVGCanvas, draw




background_content="""<?xml version="1.0" encoding="UTF-8" ?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="700" height="300">
</svg>"""



svg_1_content = img1[0]

print('svg_1_content : ', svg_1_content , type(svg_1_content))


svg_2_content = img1[1]

svg_1_element = svg2rlg(svg_1_content)

print('svg_1_element : ' , svg_1_element,  svg_1_element.width , svg_1_element.height)


svg_2_element = svg2rlg(svg_2_content)

print('svg_2_element : ' , svg_2_element,   svg_2_element.width , svg_2_element.height)

width = 350
height = 300

svg_element = svg2rlg(io.BytesIO(background_content.encode()))


print('svg_element :', svg_element, svg_element.width , svg_element.height)



d = Drawing(width, height) # setting the width and height

print('d :' , d , d.width)

print('svg_1_element : ' , svg_1_element,  svg_1_element.width , svg_1_element.height)
print('svg_2_element : ' , svg_2_element,   svg_2_element.width , svg_2_element.height)

d.add(svg_1_element)

d2 = Drawing(width, height)

d2.add(svg_2_element)

d2.translate(350,0)




s = StringIO()


c = SVGCanvas((2*width, height))


draw(d,c)

draw(d2,c)


c.save(s)
# print(s.getvalue())

with open('output.svg' , 'w')  as handler:
    
    s.seek(0)
    handler.write(s.read())
    
# for i in dir(d):
#     print(i)
    
# print(help(Drawing))

# print(help(SVGCanvas))

需要更多库:

svglib
reportlab

输出***这是一张SVG图片,这里上传了.png副本:

enter image description here

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