Есть ли код для извлечения полных молекулярных записей из большого файла sdf со списком идентификаторов? - PullRequest
0 голосов
/ 25 мая 2020

Я использую Phyton 3.7 в Spider

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

Точнее, у меня есть выбранный список из примерно 500 идентификаторов химических молекул в строках, по одному идентификатору на строку (десять цифр в каждом идентификаторе), молекулярные детали которых содержатся в большом файле sdf размером около 2 ГБ (300000 молекул, каждый запись содержит около 400 строк кода между их идентификатором и последней строкой $$$$)

Мне нужно извлечь полные 500 записей идентификаторов в один файл sdf из большого файла sdf 2G для дальнейших исследований .

Я пробовал какие-то похожие и частичные python скрипты из stackoverflow и google, но ни один из них не работал! Может ли кто-нибудь дать подсказку или несколько строк кода для тестирования?

Спасибо, Хулио

Как было предложено (спасибо, Андрей: отличная идея), чтобы упростить задачу, я разработал небольшие образцы файлы. В оригиналах каждая строка разделена символом \ n. Я добавил позиционную информацию к каждой записи, чтобы облегчить отслеживание результатов. f1.txt содержит 3 идентификатора f2.sdf содержит упрощенный образец большой базы данных 2G f3.sdf содержит требуемый файл, в данном случае для 3 идентификаторов

f1.txt

SN00061212
SN00134795
SN00107686

f2.sdf

SN00039109
 MOLSOFT 05232012283D, 1 in the large sdf list

примерно на 400 строк кода больше

$$$$
SN00357061
 MOLSOFT 05232012283D, 2 in the large sdf list, 

примерно на 400 строк кода больше

$$$$
SN00134795
 MOLSOFT 05232012283D, 3 in the large sdf list

примерно на 400 строк больше code

   $$$$
SN00061212
 MOLSOFT 05232012283D, 4 in the large sdf list

примерно на 400 строк кода больше, одна в списке коротких текстов SN1

  $$$$
SN00134796
 MOLSOFT 05232012283D, 5 in the large sdf list

примерно на 400 строк кода больше

  $$$$
SN00134795
 MOLSOFT 05232012283D, 6 in the large sdf list

примерно 400 строк кода больше, одна в списке коротких текстов SN2

  $$$$
SN00333333
 MOLSOFT 05232012283D, 7 in the large sdf list

примерно на 400 строк кода больше

  $$$$
SN00145791
  MOLSOFT 05232012283D, 8 in the large sdf list

примерно на 400 строк кода больше

  $$$$
SN00107686
 MOLSOFT 05232012283D, 9 in the large sdf list

примерно на 400 строк кода больше, одна в списке коротких текстов SN3

$$$$ 

f3.sdf

SN00061212
 MOLSOFT 05232012283D, 4 in the large sdf list

примерно на 400 строк кода больше, одна в коротком txt list SN1

  $$$$
SN00134795
 MOLSOFT 05232012283D, 6 in the large sdf list

примерно на 400 строк кода больше, одна в списке коротких текстов SN2

  $$$$
SN00107686
 MOLSOFT 05232012283D, 9 in the large sdf list

примерно на 400 строк кода больше, одна в списке коротких текстов SN3

$$$$

1 Ответ

0 голосов
/ 26 мая 2020

Для задачи можно использовать модуль re:

Если f1.txt содержит:

SN00061212
SN00134795
SN00107686

f2.sdf содержит:

SN00039109
 MOLSOFT 05232012283D

about 400 lines more of code

$$$$
SN00357061
 MOLSOFT 05232012283D

about 400 lines more of code

$$$$
SN00061212
 MOLSOFT 05232012283D

about 400 lines more of code, one in the short txt list SN1

  $$$$
SN00134796
 MOLSOFT 05232012283D

about 400 lines more of code

  $$$$
SN00134795
 MOLSOFT 05232012283D

about 400 lines more of code, one in the short txt list SN2

  $$$$
SN00333333
 MOLSOFT 05232012283D

about 400 lines more of code

  $$$$
SN00145791
  MOLSOFT 05232012283D

about 400 lines more of code

  $$$$
SN00107686
 MOLSOFT 05232012283D

about 400 lines more of code, one in the short txt list SN3

$$$$

Тогда этот скрипт:

import re

with open('f1.txt', 'r') as f_in:
    desired_ids = set(line.strip() for line in f_in if line.strip())

expr = r'({}.*?^\s*\$\$\$\$)'.format(r'^\s*(?:' + r'|'.join(re.escape(i) for i in desired_ids) + r')')
r = re.compile(expr, flags=re.DOTALL|re.M)

with open('f2.sdf', 'r') as f_in, open('f3.sdf', 'w') as f_out:
    for m in r.finditer(f_in.read()):
        print(m.group(0), file=f_out)

Производит f3.sdf:

SN00061212
 MOLSOFT 05232012283D

about 400 lines more of code, one in the short txt list SN1

  $$$$
SN00134795
 MOLSOFT 05232012283D

about 400 lines more of code, one in the short txt list SN2

  $$$$
SN00107686
 MOLSOFT 05232012283D

about 400 lines more of code, one in the short txt list SN3

$$$$

EDIT:

Вы можете увидеть регулярное выражение в реальном времени на regex101

re.DOTALL означает, что символ точки . также соответствует символам новой строки. re.M (или re.MULTILINE) означает, что символ ^ будет соответствовать началу строки, а не только началу файла. Подробнее в официальной re документации .

...