如果我们想获得一个结构文件,一种方法可以首先通过from Bio.PDB import PDBList导入PDBList类,然后创建一个类的实例pdb_list,用于与蛋白质数据数据库(PDB)交互。然后我们可以定义需要下载的PDB ID(这里为”4hhb”),这里代表的是人类脱氧血红蛋白的结构。接下来,通过调用retrieve_pdb_file方法,指定下载的文件格式为MMCIF,并将文件保存到指定的目录”data/PDB_files"中。最后为了认下载操作是否成功,我们可以打印出下载的文件名。
from Bio.PDB import PDBListpdb_list = PDBList()pdb_id = "4hhb"pdb_filename = pdb_list.retrieve_pdb_file(pdb_id, pdir="data/PDB_files", file_format="mmCif")print(pdb_filename)

运行结束后,各位小伙伴可以在 data 的文件夹中看到一个名为 4hhb.cif 的结构文件。
当然,除了使用 Biopython 文件下载那样获取结构文件,我们也可以调用 API,通过 PDB ID 在网页上检索分子的信息。我们可以通过修改 URL 来访问 PDB 不同的条目信息以及目的文件。
在 PDB 数据库 API 的格式如下:
https://data.rcsb.org/rest/v1/core/<资源类型>/<标识符>
例如,要获取 PDB ID 为 4hhb 的完整条目,你可以使用以下链接:
https://data.rcsb.org/rest/v1/core/entry/4hhb
大家可以复制这个链接!大家可以在浏览器中显示与 4HHB 相关的信息。
使用 REST API(REST 是表述性状态传递的英文缩写,API 是应用编程接口)可以做很多有趣的事情。比如我们可以检索某个条目主要引用文献的 PubMed 注释。所以我们修改<资源类型>为 pubmed:
https://data.rcsb.org/rest/v1/core/pubmed/4hhb
大家可以看到显示的结果是一堆代码,其实这些结果中的数据是以一种叫做 JSON 的格式返回的。这是一种常用的网页 API 返回格式,因为它可以被编程处理。其格式类似于 Python 字典,包含键和值。
Tip:
JSON 是一种简单易懂的格式,用来在电脑和应用程序之间传递数据。它的结构类似于一个包含键和值的表格或者字典。
每条数据都有一个“键”(相当于标签)和一个对应的“值”(相当于内容)。比如,如果我们想存储一个人的信息,JSON 会把这些信息整理成成对的数据,就像这样:
{"名字": "小明","年龄": 25,"城市": "北京"}
这里,"名字"是键,"小明"是对应的值。同样的,"年龄"和"城市"也是键,而它们对应的值分别是25和北京。
JSON 格式清晰、简单,易于理解,广泛应用于数据传递和处理,尤其适合编程语言自动读取和操作。
REST API 在通过编程访问时变得更加有用。我们将使用 Python 从指定的 URL 获取数据,并将其转换为我们可以操作的格式。我们将使用一个名为 requests 的 Python 库。requests 用于从网站和 URL 获取信息。
import requests要从 URL 获取信息,我们使用 requests.get 方法。该方法的参数是我们想从中获取信息的 URL。
data = requests.get("https://data.rcsb.org/rest/v1/core/entry/4hhb")
现在,变量 data 包含了我们请求的结果和其他相关信息。如果请求成功,它将返回一个状态码 200。这是网页 URL 的一个功能。如果请求成功,服务器将返回状态码 200。这对于任何网站都适用。大家可能熟悉的另一个状态码是 404,当资源未找到时会返回这个状态码。
请注意,status_code 并不是 data 关联的一个函数,所以不需要使用 ()。
data.status_code输出的应该是 200

我们可以通过调用 .json() 方法查看与请求关联的 JSON 数据,我们将其保存到一个名为 info_4hhb 的变量中。现在,这个变量类似于一个 Python 字典,它是一种由键值对组成的数据类型。
info_4hhb = data.json()一旦我们以 JSON 格式加载了返回的值,我们可以通过 变量.keys() 方法查看与该条目关联的所有关键词。
info_4hhb.keys()输出的是 dict_keys(['audit_author', 'cell', 'citation', …])

变量 info_4hhb 是一个 Python 字典,这意味着我们可以使用如下语法访问字典中的信息:
dictionary_name["key_name"]例如:
info_4hhb["exptl"]会输出:[{'method': 'X-RAY DIFFRACTION'}]
info_4hhb["struct_keywords"]会输出:{'pdbx_keywords': 'OXYGEN TRANSPORT', 'text': 'OXYGEN TRANSPORT'}
info_4hhb["struct"]会输出:{'title': 'THE CRYSTAL STRUCTURE OF HUMAN DEOXYHAEMOGLOBIN AT 1.74 ANGSTROMS RESOLUTION'}

我们还可以使用 PDB 数据 API,通过改变 URL 来检索关于聚合物实体(蛋白质或核酸)之间接口的信息。
查询接口信息的 URL 格式如下:
https://data.rcsb.org/rest/v1/core/interface///
在下面的代码中,我们获取了 assembly 1 的第一个接口信息(这个 PDB 中只有一个 assembly)。
my_query = {"query": {"type": "terminal","service": "text","parameters": {"attribute": "struct_keywords.pdbx_keywords","operator": "contains_phrase","value": '"oxygen storage"'}},"request_options": {"paginate": {"start": 0,"rows": 50,},"sort": [{"sort_by": "rcsb_accession_info.initial_release_date","direction": "asc"}]},"return_type": "entry"}my_query = json.dumps(my_query)
刚才我们的代码是生成一个查询对象,使用 JSON 格式来描述查询条件,以便从一个数据库或API中提取相关数据。具体来说,它可能是查询某个与PDB 相关的API或数据库,用于检索蛋白质结构数据。
query 部分:
"type": "terminal" 表示查询是一个终端类型的查询,可能是直接执行的查询。
"service": "text" 表示查询目标是文本服务,可能与文本数据有关。
"parameters" 定义了查询的条件:
"attribute": "struct_keywords.pdbx_keywords" 表示查询的属性是struct_keywords.pdbx_keywords,这可能是与结构相关的关键字。
"operator": "contains_phrase" 表示操作符是包含短语。
"value": '"oxygen storage"' 表示要查找包含 "oxygen storage" 这个短语的记录。
request_options 部分:
"paginate" 定义分页选项:
"start": 0 表示从第0条记录开始检索。
"rows": 50 表示每页返回50条记录。
"sort" 定义排序选项:
"sort_by":"rcsb_accession_info.initial_release_date"表示根据 rcsb_accession_info.initial_release_date 字段排序。
"direction": "asc" 表示按照升序排序,意即从最早的发布日期开始排序。
return_type: 指定返回的类型为 "entry",即返回的是数据项的条目。

最后,my_query = json.dumps(my_query) 将上面构建的查询字典转换为 JSON 格式的字符串,以便发送到 API 或数据库进行查询。
interface = requests.get("https://data.rcsb.org/rest/v1/core/interface/4hhb/1/1")interface.status_code
# 输出:200
interface_info = interface.json()interface_info["rcsb_interface_info"]
# 输出:{'polymer_composition': 'Protein (only)', 'interface_character': 'hetero', ...}

大家可以试着更改 URL 中的数字,看看结果有何变化?
我们刚刚使用的 API 是基于 PDB “数据” 的API。然而,PDB 还有另一个 API,称为“搜索” API,它允许你基于关键词、宿主物种、序列相似性等进行搜索。虽然搜索 API 可能比较复杂,但在 PDB 网站上有详细的文档支持。
该 API 的 URL 格式如下:
https://search.rcsb.org/rcsbsearch/v2/query?json={search-request}我们使用 requests.get 方法和我们的搜索查询以及搜索 API 的 URL 格式来获取数据。其中,search-request 是一个包含搜索参数的 JSON(类似于 Python 字典)。我们将创建一个 Python 字典,然后使用 json 库将其转换为 JSON(搜索 API 所需的数据格式)。
data = requests.get(f"https://search.rcsb.org/rcsbsearch/v2/query?json={my_query}")results = data.json()results

我们的查询结果告诉我们,搜索返回了 671 个结果(total_count)。result_set 关键字包含了结果列表。result_set 中每个值的 identifier 键告诉我们搜索结果的 PDB ID。大家可以看到尽管搜索结果显示有 671 个结果,但我们只获得了 10 个值。这是因为 API 总是会计算结果的数量,但除非我们要求更多,否则只返回 10 个结果。
现在,我们可以将此与 Biopython 或数据 API 结合使用,以获取关于结构的更多信息。例如,如果我们想获取该结构发表论文的标题,可以这样做:
first_result = results["result_set"][0]["identifier"]print(first_result)data = requests.get(f"https://data.rcsb.org/rest/v1/core/entry/{first_result}")result = data.json()result[“struct"]

接下来的代码展示了使用 Biopython 对这些结构进行的较复杂分析。如果你对编程不太熟悉,接下来的几段代码可能会比较难理解。不过,它们展示了如何通过编程方式获取搜索结果并使用 Python 进行数据分析。分析的最后一步打印出在这些结构中最常见的与铁原子相邻的残基。
这个程序分为多个步骤:
·使用 Biopython 下载所有结构的 mmCIF 文件。
·使用 Biopython 创建结构对象,筛选原子,并找到与铁原子相邻的残基。
·使用 Python 的 Counter 函数统计残基组合的出现次数。
第一步
from Bio.PDB import PDBList
# 创建 PDBList 类的实例
pdb_list = PDBList()
# 下载所有的结构文件
for result in results["result_set"]:
pdb_id = result["identifier"].lower()
# 使用 retrieve_pdb_file 方法下载 MMCIF 文件
pdb_filename = pdb_list.retrieve_pdb_file(pdb_id, pdir="pdb_files", file_format="mmCif")
第二步
from Bio.PDB.MMCIFParser import MMCIFParser
from Bio.PDB import NeighborSearch
from collections import Counter
# 创建 MMCIFParser 对象用于解析 mmCIF 文件
parser = MMCIFParser(QUIET=True)
# 定义用于识别邻近残基的最大距离(以埃为单位)
cutoff_distance = 5
# 初始化一个字典用于存储每个蛋白质结构的邻近残基
residue_neighbors = {}
# 'results' 变量包含搜索结果
for result in results["result_set"]:
pdb_id = result["identifier"].lower()
# 使用 PDB ID 解析该蛋白质结构的 mmCIF 文件
structure = parser.get_structure(pdb_id, f"pdb_files/{pdb_id}.cif")
# 从蛋白质结构中提取所有原子
atoms = list(structure.get_atoms())
# 创建 NeighborSearch 对象进行邻近搜索
neighbor_search = NeighborSearch(atoms)
# 初始化一个列表用于存储此蛋白质结构的邻近残基
neighbor_list = []
for atom in atoms:
# 检查原子是否为铁原子
if atom.element == "FE":
# 获取铁原子的父残基
iron_residue = atom.get_parent()
# 查找在给定距离内的邻近原子
neighbors = neighbor_search.search(atom.get_coord(), cutoff_distance)
for neighbor in neighbors:
# 获取邻近原子的父残基
residue = neighbor.get_parent()
# 如果邻近残基与铁原子残基不同,则将其添加到列表中
if residue != iron_residue:
neighbor_list.append(residue)
# 使用 PDB ID 作为键,将唯一的邻近残基存储在字典中
residue_neighbors[pdb_id] = set(neighbor_list)
第三步
# 统计邻近残基的类型
combination_counts = Counter()
for pdb_id, neighbors in residue_neighbors.items():
# 提取每个邻近残基的名称
resname = [x.get_resname() for x in neighbors if x.get_resname()]
# 统计每个残基名称在当前组合中的出现次数
res_counts = Counter(resname)
# 将残基统计信息转换为 (残基, 次数) 的元组,并按残基名称排序
combination = tuple(sorted(res_counts.items()))
# 更新组合统计
combination_counts.update([combination])
# 获取最常见的残基组合
most_common_combinations = combination_counts.most_common()
# 获取前五种最常见的残基组合
top_5_combinations = combination_counts.most_common(5)
print("\n与铁原子邻近的最常见残基组合前五名:")
for combination, count in top_5_combinations:
combination_str = ', '.join([f"{count} {residue}" for residue, count in combination])
print(f"组合:{combination_str}, 次数:{count}”)
- 整个代码如下图:

当我们运行后,他会执行一会儿,最后给出与铁原子邻近的最常见残基组合前五名的结果。
组合:2 HIS, 1 HOH, 1 VAL, 次数:4
组合:1 CMO, 2 HIS, 1 VAL, 次数:3
组合:2 HIS, 1 HOH, 1 OXY, 1 VAL, 次数:2
组合:5 HIS, 2 HOH, 2 VAL, 次数:2
组合:4 HIS, 2 HOH, 2 VAL, 次数:2

在本节课程中,小亚老师带大家了如何使用 Python 与蛋白质数据库(PDB)进行交互,并通过 PDB 的 Web API 检索生物分子结构信息。我们首先通过 Biopython 中的 PDBList 类下载结构文件,并展示了如何使用 PDB 的 REST API 获取特定条目信息。同时,我们学习了如何使用 requests 库从 API 中获取数据,并以 JSON 格式处理这些数据。
在本节课程中,我们还实践了如何基于 API 返回的数据进行进一步的分析,例如使用 Biopython 对结构文件进行解析,识别蛋白质中与铁原子邻近的残基组合,并统计最常见的邻近组合。我们不仅了解了 PDB 数据库的 Web API 结构,还了解了如何使用 Python 代码获取和分析蛋白质结构数据。这些技能对于深入探索结构生物学及其应用具有重要意义。
这节课其实非常重要,对于 API 的运用不仅体现在 PDB 数据库中。在生物学中有许许多多的官方数据库都提供访问,大家可以运用这种方法进行尝试,熟练之后,可以更快速的获得想要的结果。



沪公网安备 31011002003500