Создание 2d изображений молекул из данных FTP PubChem

Вместо того, чтобы сканировать веб-сайт PubChem, я бы предпочел быть хорошим и генерировать изображения локально с ftp-сайта PubChem:

ftp://ftp.ncbi.nih.gov/pubchem/specifications/

Единственная проблема заключается в том, что я ограничен OSX и Linux, и я не могу найти способ программно генерировать 2d изображения, которые они имеют на своем сайте. Смотрите этот пример:

https://pubchem.ncbi.nlm.nih.gov/compound/6

Под заголовком "2D Структура" у нас есть это изображение здесь:

https://pubchem.ncbi.nlm.nih.gov/image/imgsrv.fcgi?cid=6&t=l

Это то, что я пытаюсь создать.

2 ответа

Если вы хотите что-то нестандартное, я бы предложил использовать molconvert от ChevAxon's Marvin ( https://www.chemaxon.com/products/marvin/), который является бесплатным для академиков. Его можно легко использовать из командной строки, и он поддерживает множество форматов ввода и вывода. Так что для вашего примера это будет:

molconvert "png" -s "C1=CC(=C(C=C1[N+](=O)[O-])[N+](=O)[O-])Cl" -o cdnb.png

В результате на следующем изображении:

1-хлор-2,4-динитробензол

Он также позволяет устанавливать такие параметры, как ширина, высота, качество, цвет фона и так далее.


Однако, если вы программист, я бы определенно рекомендовал RDKit. Следует код, который генерирует изображения для пары соединений, представленных в виде улыбок.

from rdkit import Chem
from rdkit.Chem import Draw

ms_smis = [["C1=CC(=C(C=C1[N+](=O)[O-])[N+](=O)[O-])Cl", "cdnb"],
           ["C1=CC(=CC(=C1)N)C(=O)N", "3aminobenzamide"]]
ms = [[Chem.MolFromSmiles(x[0]), x[1]] for x in ms_smis]

for m in ms: Draw.MolToFile(m[0], m[1] + ".svg", size=(800, 800))

Это дает вам следующие изображения:

cdnb

Так что я также написал ребятам из PubChem по электронной почте, и они очень быстро ответили мне:

Единственный доступ к изображениям, который у нас есть, - через службу загрузки: https://pubchem.ncbi.nlm.nih.gov/pc_fetch/pc_fetch.cgi
Вы можете запросить до 50000 изображений одновременно.

Что лучше, чем я ожидал, но все же не удивительно, поскольку требует загрузки вещей, которые я теоретически мог бы генерировать локально. Так что я оставляю этот вопрос открытым, пока какая-то добрая душа не напишет библиотеку с открытым исходным кодом, чтобы сделать то же самое.

Редактировать:

Я полагаю, что с тем же успехом могу спасти людей, если они будут делать то же самое, что и я. Я создал Ruby Gem на механизированной основе для автоматизации загрузки изображений. Пожалуйста, будьте добры к своим серверам и загружайте только то, что вам нужно.

https://github.com/zachaysan/pubchem

gem install pubchem

Вариант с открытым исходным кодом - Indigo Toolkit, который также содержит предварительно скомпилированные пакеты для Linux, Windows и MacOS и языковые привязки для библиотек Python, Java, .NET и C. Я выбрал бету 1.4.0.

У меня был такой же интерес, как и у вас, в преобразовании SMILES в 2D-структуры, и я адаптировал свой Python для ответа на ваш вопрос и сбора информации о времени. Он использует загрузку PubChem FTP (Compound/Extras) CID-SMILES.gz. Следующий сценарий представляет собой реализацию локального преобразователя SMILES в 2D-структуру, который считывает диапазон строк из файла PubChem CID-SMILES изомерных SMILES (который содержит более 102 миллионов составных записей) и преобразует SMILES в изображения PNG 2D-конструкции. В трех тестах с преобразованием 1000 SMILES в структуру потребовалось 35, 50 и 60 секунд для преобразования 1000 SMILES при смещении строки файла 0, 100 000 и 10 000 000 на моем ноутбуке с Windows 10 (процессор Intel i7-7500U, 2,70 ГГц) с твердотельным накопителем и запущенным Python 3.7.4. Общий размер 3000 файлов составил 100 МБ.

from indigo import *
from indigo.renderer import *
import subprocess
import datetime

def timerstart():
    # start timer and print time, return start time
    start = datetime.datetime.now()
    print("Start time =", start)

    return start

def timerstop(start):
    # end timer and print time and elapsed time, return elapsed time
    endtime = datetime.datetime.now()
    elapsed = endtime - start
    print("End time =", endtime)
    print("Elapsed time =", elapsed)

    return elapsed

numrecs = 1000
recoffset = 0 # 10000000    # record offset
starttime = timerstart()

indigo = Indigo()
renderer = IndigoRenderer(indigo)

# set render options
indigo.setOption("render-atom-color-property", "color")
indigo.setOption("render-coloring", True)
indigo.setOption("render-comment-position", "bottom")
indigo.setOption("render-comment-offset", "20")
indigo.setOption("render-background-color", 1.0, 1.0, 1.0)
indigo.setOption("render-output-format", "png")

# set data path (including data file) and output file path
datapath = r'../Download/CID-SMILES'
pngpath = r'./2D/'

# read subset of rows from data file
mycmd = "head -" + str(recoffset+numrecs) + " " + datapath + " | tail -" + str(numrecs) 
print(mycmd)
(out, err) = subprocess.Popen(mycmd, stdout=subprocess.PIPE, shell=True).communicate()

lines = str(out.decode("utf-8")).split("\n")
count = 0
for line in lines: 
    try:
        cols = line.split("\t")   # split on tab
        key = cols[0]             # cid in cols[0]
        smiles = cols[1]          # smiles in cols[1]
        mol = indigo.loadMolecule(smiles)
        s = "CID=" + key
        indigo.setOption("render-comment", s)
        #indigo.setOption("render-image-size", 200, 250)
        #indigo.setOption("render-image-size", 400, 500)
        renderer.renderToFile(mol, pngpath + key + ".png")
        count += 1
    except:
        print("Error processing line after", str(count), ":", line)
        pass

elapsedtime = timerstop(starttime)
print("Converted", str(count), "SMILES to PNG")
Другие вопросы по тегам