Python读sdf/mdl坐标:如何读到两个空格?

Python read sdf/mdl coordinates: How to read until two spaces are met?

我想读取一些.sdf 文件(实际上是.mdl 文件,但当我下载它们时它们显示为.sdf),以便制作一个程序将它们转换为另一种格式。 .sdf 文件模拟分子,但这与那里无关。

我想读取坐标而忘记了债券,所以我需要从这样的文件格式中读取:

ALA
  CCTOOLS-0424210918

 13 12  0  0  1  0  0  0  0  0999 V2000
    2.2810   26.2130   12.8040 N   0  0  0  0  0
    1.1690   26.9420   13.4110 C   0  0  0  0  0
    1.5390   28.3440   13.8740 C   0  0  0  0  0
    2.7090   28.6470   14.1140 O   0  0  0  0  0
    0.6010   26.1430   14.5740 C   0  0  0  0  0
    0.5230   29.1940   13.9970 O   0  0  0  0  0
    2.0330   25.2730   12.4930 H   0  0  0  0  0
    3.0800   26.1840   13.4360 H   0  0  0  0  0
    0.3990   27.0670   12.6130 H   0  0  0  0  0
   -0.2470   26.6990   15.0370 H   0  0  0  0  0
    0.3080   25.1100   14.2700 H   0  0  0  0  0
    1.3840   25.8760   15.3210 H   0  0  0  0  0
    0.7530   30.0690   14.2860 H   0  0  0  0  0
  1  2  1  0  0  0
  1  7  1  0  0  0
  1  8  1  0  0  0
  2  3  1  0  0  0
  2  5  1  0  0  0
  2  9  1  0  0  0
  3  4  2  0  0  0
  3  6  1  0  0  0
  5 10  1  0  0  0
  5 11  1  0  0  0
  5 12  1  0  0  0
  6 13  1  0  0  0
M  END
$$$$

我想从第 3 行开始读到数字前只有 2 spaces。

如果你:

file=open('ALA_model.sdf',mode="r")
string_list=file.readlines()
file.close()
datasplit=[]
for i in range(len(string_list)):
   datasplit.append(string_list[i].split(" "))

(快速提醒:ALA_model.sdf 是上面文件的名称,但不是我必须处理的唯一文件。请随意使用上面的 ALA 文件,因为我从 http://ligand-expo.rcsb.org/reports/A/ALA/ALA_model.sdf)

下载

你会发现

 datasplit[3]=['', '13', '12', '', '0', '', '0', '', '1', '', '0', '', '0', '', '0', '', '0', '', '0999', 'V2000\n']

这意味着开始阅读。那么我们有:

datasplit[4]=['', '', '', '', '2.2810', '', '', '26.2130', '', '', '12.8040', 'N', '', '', '0', '', '0', '', '0', '', '0', '', '0\n']

我只需要前三个数字和 letter/atom,但我自己可以处理。

最后但同样重要的是,

datasplit[17]=['', '', '1', '', '2', '', '1', '', '0', '', '0', '', '0\n']

第一行是我不想看的

那么当列表中的前两个 str 对象是 space 字符串时,如何停止读取? 我相信在这种情况下它会来自 string_list[4:16],但我还有其他 .sdf 文件可以读取,每个文件都有不同的长度,我想从中构建一个函数,使它成为可迭代的,你知道的,无需为每个脚本制作脚本。

综上所述,在不关心格式的情况下,我们如何遍历第一个 three/four 个字符串值为 space 的列表,直到第三个字符串值为一个数字?

在你的情况下,我会逐行读取文件并检查每一行是否有四个 spaces。

string_list = []
with open('ALA_model.sdf') as file:
    for line in file:
        if line.startswith('    '):
            string_list.append(line)
        else:
            # finish reading here
            continue

此示例不包括跳过第一行并处理以 space 开头的第 4 行,但我认为您可以处理这个问题。

另一种选择可能是使用 file.read() 读取整个文件,并重复匹配所有以 3 个或更多空格开头后跟可选 - 和使用模式的数字的行。

^ {3,}-?\d.*(?:\r?\n {3,}-?\d.*)*
  • ^ 字符串开头
  • {3,}-?\d.*匹配3个或更多空格,可选-,一个数字和该行的其余部分
  • (?:\r?\n {3,}-?\d.*)* 可选择重复换行符和相同的模式

Regex demo

然后你可以使用 splitlines()split() 每一行,将前 4 项附加到 datasplit.

例如

import re
from pprint import pprint

file = open('ALA_model.sdf', mode="r")
content = file.read()
file.close()
match = re.search(r"^ {3,}-?\d.*(?:\r?\n {3,}-?\d.*)*", content, re.M)
datasplit = []

if match:
    for line in match.group().splitlines():
        datasplit.append([part for part in line.split()][:4])

pprint(datasplit)

输出

[['2.2810', '26.2130', '12.8040', 'N'],
 ['1.1690', '26.9420', '13.4110', 'C'],
 ['1.5390', '28.3440', '13.8740', 'C'],
 ['2.7090', '28.6470', '14.1140', 'O'],
 ['0.6010', '26.1430', '14.5740', 'C'],
 ['0.5230', '29.1940', '13.9970', 'O'],
 ['2.0330', '25.2730', '12.4930', 'H'],
 ['3.0800', '26.1840', '13.4360', 'H'],
 ['0.3990', '27.0670', '12.6130', 'H'],
 ['-0.2470', '26.6990', '15.0370', 'H'],
 ['0.3080', '25.1100', '14.2700', 'H'],
 ['1.3840', '25.8760', '15.3210', 'H'],
 ['0.7530', '30.0690', '14.2860', 'H']]

Python demo