RDKit: Как изменить размер шрифта метки атома?

При рисовании структур с помощью RDKit размер шрифта метки атома и размер кольца не находятся в хорошей пропорции. Этикетки либо слишком маленькие, либо слишком большие, либо смещены.

К сожалению, документации по этому поводу скудно. Я нашел это: https://rdkit.org/docs/source/rdkit.Chem.Draw.MolDrawing.html Но я не знаю, связано ли это и как мне пришлось бы это собрать. Мне не хватает простых практических примеров кода.

Я также пробовал Draw.MolToQPixmap, но там я испытал, что метки атомов не выровнены, и до сих пор я узнал, что причина в сложности сделать эту кроссплатформенную согласованность и, кроме того, Draw.MolToPixmap использует старый код рисования. Я должен использовать, например, Draw.MolToImage вместо этого. Но там, как и у Draw.MolToFile, размер шрифта просто маловат. Я не уверен, что это проблема кроссплатформенности (я использую Win10). Итак, решением было бы просто установить размер шрифта, но как?

Я знаю, что есть список рассылки RDKit, где я задал этот вопрос уже без ответа. Здесь, на SO, возможно, есть более широкая аудитория, и я могу прикрепить изображения для иллюстрации.

Код:

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))

Результат: (используется Draw.MolToFile, выравнивание в порядке, но слишком маленькие метки атомов)

введите описание изображения здесь

Результат: (используется Draw.MolToQPixmap, смещено и / или шрифт слишком большой для маленьких изображений)

введите описание изображения здесь

введите описание изображения здесь

Изменить: (по предложению @Oliver Scott)

Я получаю в 3 раза одинаковый результат с одинаковым размером шрифта. Я должно быть где-то глупая ошибка или недоразумение.

Код:

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)

Результат:

6.0
12.0
24.0

введите описание изображения здесь


person theozh    schedule 13.11.2020    source источник


Ответы (3)


Новый код рисования RDKit более гибкий, чем эти старые функции. Попробуйте использовать код рисования rdMolDraw2D. Вы можете установить параметры рисования, как показано ниже. Документация содержит список доступных опций:

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') 

Минимальный размер шрифта по умолчанию - 12, максимальный - 40.

Результат:

RDKit молекула PNG

Чтобы попасть в образ PIL, вы можете сделать это так:

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.
person Oliver Scott    schedule 13.11.2020
comment
Спасибо за пример! На самом деле мне нужно изображение QPixmap для PyQt QTableWidget .... Если у меня есть изображение PIL (через Draw.MolToImage), я мог бы преобразовать его в QPixmap. Итак, есть идеи, как получить PNG в PIL или QPixmap? Собственно, в итоге я не хочу сохранять изображения на диск, а просто отображать их в виде таблицы. - person theozh; 13.11.2020
comment
См. Правки выше, это работает? Таким образом вы ничего не записываете на диск. - person Oliver Scott; 13.11.2020
comment
по какой-то причине d.drawOptions().minFontSize = 22 не приводит к увеличению размера шрифта, тогда как d.SetFontSize(22) делает. Спасибо за подпрограмму из PNG в PIL, я бы не нашел ее самостоятельно. - person theozh; 13.11.2020
comment
Ах, странно, может быть, мы используем разные версии RDKit. Я не заметил SetFontSize функций, это, наверное, более чистое решение для изменения размера шрифта. Буду признателен, если вы отметите ответ как принятый, если он вам хоть как-то помог. Спасибо! - person Oliver Scott; 13.11.2020
comment
хммм, к сожалению, проблема пока не решена. Я использую RDKit 2020.03, я не могу его воспроизвести: при первом запуске скрипта размер шрифта может быть больше, но при втором запуске, установив другой размер шрифта, размер останется прежним. Я, должно быть, все еще делаю что-то не так. - person theozh; 13.11.2020
comment
хммм, я использую RDKit 2020.09.1, можно ли поделиться фрагментом вашего скрипта? - person Oliver Scott; 13.11.2020
comment
может быть проблема с версией? Мне не удалось найти документацию по 2020.03 для проверки. На странице RDKit я вижу только документацию 2020.09.01 ... нет ссылки на документацию 2020.03. - person theozh; 13.11.2020
comment
Позвольте нам продолжить это обсуждение в чате. - person Oliver Scott; 13.11.2020
comment
Думаю, я нашел это. Если вы добавите строку print(d.FontSize()) до того, как вы ее установите, в результате я получу 0.5. Я предполагаю, что размер шрифта - это относительный размер или вид коэффициента масштабирования, но не абсолютный размер в пунктах. Если вы установите размер шрифта в диапазоне от 0,5 до 1,5, я получу изменение. Если вы наберете 12 или 22, это, вероятно, превысит максимум ... довольно странно и плохо задокументировано. - person theozh; 13.11.2020
comment
Размер шрифта предположительно в пикселях, так что я предполагаю относительно размера изображения? Хотя в документации сказано примерно .... - person Oliver Scott; 13.11.2020

Вы можете использовать SetPreferCoordGen и 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))

Вы получаете это изображение PIL

img

Работает в 2020.09, но в 2020.03 не тестировал.

person rapelpy    schedule 13.11.2020
comment
Спасибо. Что показывает ваш пример? Регулировка ориентации структуры в соответствии с p и, следовательно, лучшее выравнивание меток атомов? Но как насчет изменения размера шрифта с помощью Draw.MolToImage()? - person theozh; 13.11.2020
comment
@theozh Это просто способ RDKit получить более красивые изображения в хороших пропорциях. Я просто подумал, это то, что ты хотел. MolToImage() не имеет возможности изменить размер шрифта. - person rapelpy; 13.11.2020
comment
спасибо @rapelpy, это тоже полезно. Собственно, я имел в виду выравнивание метки атома относительно колец (в случае Draw.MolToQPixmap()), а не выравнивание структуры на холсте. Надеюсь, ваше предложение также работает вместе с rdMolDraw2D.MolDraw2DCairo(). Ваша ориентированная структура действительно выглядит лучше. - person theozh; 13.11.2020

Благодаря помощи @Oliver Scott я наконец получил то, что искал: по-видимому, размер шрифта относительный (по умолчанию 0,5), а не абсолютный в пунктах, по крайней мере, в RDKit 2020.03, который я использую. Может это изменилось в RDKit 2020.09?

Код: (для получения файлов PNG)

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)

Результат:

введите описание изображения здесь

Код: (чтобы получить QPixmap, например, для 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
person theozh    schedule 13.11.2020