theozh
theozh

Reputation: 25734

RDKit: How to change the atom label fontsize?

When drawing structures with RDKit, the atom label font size and the ring size are not in a good proportion. The labels are either too small or too large or misaligned.

Unfortunately, the documentation about this is meager. I found this: https://rdkit.org/docs/source/rdkit.Chem.Draw.MolDrawing.html But I don't know whether this is related and how I would have to put it together. I'm missing simple practical code examples.

I tried also Draw.MolToQPixmap, but there I experienced that of the atom labels are misaligned and so far I learnt that the reason is the difficulty to make this cross-platform consistent and furthermore Draw.MolToPixmap uses old drawing code. I should use e.g. Draw.MolToImage instead. But there similar like with Draw.MolToFile the font size is simply too small. I'm not sure whether this is a cross-platform issue as well (I'm on Win10). So, the solution would be to simply set the fontsize, but how?

I know that there is a RDKit mailing list where I asked this question already without an answer so far. Here on SO, there is maybe a broader audience and I can attach images for illustration.

Code:

from rdkit import Chem
from rdkit.Chem import Draw

smiles = ' FC1OC2N3C4[Si]5=C6B7C(C=CC6=CC4=CC2=CC1)C=CC=C7C=C5C=C3'
mol = Chem.MolFromSmiles(smiles)
img = Draw.MolToFile(mol,"Test.png",size=(300,150))

Result: (using Draw.MolToFile, alignment ok, but too small atom labels)

enter image description here

Result: (using Draw.MolToQPixmap, misaligned and/or font too large for small pictures)

enter image description here

enter image description here

Edit: (with the suggestion of @Oliver Scott)

I get 3 times the same output with the same fontsize. I must be a stupid mistake or misunderstanding somewhere.

Code:

from rdkit.Chem.Draw import rdMolDraw2D
from rdkit import Chem

smiles = 'FC1OC2N3C4[Si]5=C6B7C(C=CC6=CC4=CC2=CC1)C=CC=C7C=C5C=C3'
mol = Chem.MolFromSmiles(smiles)
    
def drawMyMol(fname, myFontSize):
    d = rdMolDraw2D.MolDraw2DCairo(350, 300)
    d.SetFontSize(myFontSize)
    print(d.FontSize())
    d.DrawMolecule(mol)
    d.FinishDrawing()
    d.WriteDrawingText(fname)
    
drawMyMol("Test1.png", 6)
drawMyMol("Test2.png", 12)
drawMyMol("Test3.png", 24)

Result:

6.0
12.0
24.0

enter image description here

Upvotes: 2

Views: 4302

Answers (3)

rapelpy
rapelpy

Reputation: 1869

You can use SetPreferCoordGen and Compute2DCoords.

from rdkit import Chem
from rdkit.Chem import Draw
from rdkit.Chem import rdDepictor
rdDepictor.SetPreferCoordGen(True)

smiles = 'FC1OC2N3C4[Si]5=C6B7C(C=CC6=CC4=CC2=CC1)C=CC=C7C=C5C=C3'
mol = Chem.MolFromSmiles(smiles)
rdDepictor.Compute2DCoords(mol)
PILmol = Draw.MolToImage(mol, size=(300,150))

You get this PIL Image

img

Works in 2020.09, but I did not test it in 2020.03.

Upvotes: 1

theozh
theozh

Reputation: 25734

Thanks to the help of @Oliver Scott, I finally got what I was looking for: Apparently, the font size is relative (default 0.5), not absolute in points, at least in RDKit 2020.03, which I am using. Maybe this has changed in RDKit 2020.09?

Code: (to get PNGs files)

from rdkit.Chem.Draw import rdMolDraw2D
from rdkit import Chem

smiles = 'FC1OC2N3C4[Si]5=C6B7C(C=CC6=CC4=CC2=CC1)C=CC=C7C=C5C=C3'
mol = Chem.MolFromSmiles(smiles)

def myMolToPNG(fname, myFontSize):
    d = rdMolDraw2D.MolDraw2DCairo(350, 300)
    d.SetFontSize(myFontSize)
    d.DrawMolecule(mol)
    d.FinishDrawing()
    d.WriteDrawingText(fname)

myMolToPNG("Test1.png", 0.5)
myMolToPNG("Test2.png", 1.0)
myMolToPNG("Test3.png", 1.5)

Result:

enter image description here

Code: (to get a QPixmap, e.g for a PyQt QTableWidget)

from rdkit.Chem.Draw import rdMolDraw2D
from rdkit import Chem
from PyQt5.QtGui import QPixmap

smiles = 'FC1OC2N3C4[Si]5=C6B7C(C=CC6=CC4=CC2=CC1)C=CC=C7C=C5C=C3'
mol = Chem.MolFromSmiles(smiles)

def myMolToQPixmap(myFontSize):
    d = rdMolDraw2D.MolDraw2DCairo(350, 300)
    d.SetFontSize(myFontSize)
    d.DrawMolecule(mol)
    d.FinishDrawing()
    png = d.GetDrawingText()
    pixmap = QPixmap()
    pixmap.loadFromData(png)
    return pixmap

Upvotes: 1

Oliver Scott
Oliver Scott

Reputation: 1783

The newer RDKit drawing code is more flexible than these older functions. Try using the rdMolDraw2D drawing code. You can set the options for drawing as below. The documentation has a list of the available options:

from rdkit.Chem.Draw import rdMolDraw2D
from rdkit import Chem

smiles = 'FC1OC2N3C4[Si]5=C6B7C(C=CC6=CC4=CC2=CC1)C=CC=C7C=C5C=C3'
mol = Chem.MolFromSmiles(smiles)

# Do the drawing.
d = rdMolDraw2D.MolDraw2DCairo(350, 300)
d.drawOptions().minFontSize = 22
d.DrawMolecule(mol)
d.FinishDrawing()
d.WriteDrawingText('test.png') 

The default minimum font size is 12 and the max is 40.

Result:

RDKit molecule PNG

To get into a PIL image you could do it like this:

from PIL import Image
import io

# Change the last line of the above to get a byte string.
png = d.GetDrawingText() 

# Now read into PIL.
img = Image.open(io.BytesIO(png))

# Now you can do whatever you need to do with the PIL image.

Upvotes: 2

Related Questions