化学信息学 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 上
我非常感谢任何帮助,提前致谢! :)
无法弄清楚如何在
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副本: