PDB Database - 高质量 RCSB PDB 蛋白质结构筛选与过滤

news2024/11/22 20:42:41

欢迎关注我的CSDN:https://spike.blog.csdn.net/
本文地址:https://spike.blog.csdn.net/article/details/132307119

PDB

Protein Data Bank (PDB) 是一个收集和存储三维结构数据的公共数据库,主要包括蛋白质和核酸分子。PDB 由美国、欧洲和日本三个机构共同管理,每周更新一次。PDB 的目的是为生物学、生物化学、生物物理学和医学等领域的研究者提供结构信息,促进科学发现和教育。PDB 的数据可以通过网站、FTP 服务器或应用程序接口 (API) 免费获取,也可以通过各种工具和服务进行可视化、分析和下载。

根据不同维度,从 RCSB PDB 筛选与过滤出高质量的数据,用于下游任务的分析与处理,主要包括以下维度:

  1. 按 发布时间 (Release Date) 过滤。
  2. 按 单体 (Monomer) 或 多聚体 (Multimer) 过滤。
  3. 按 氨基酸类型,是RNA\DNA,还是蛋白质 (Protein) 过滤。
  4. 按 结构分辨率 (Resolution) 过滤。
  5. 按 相同氨基酸占比 过滤。
  6. 按 最短蛋白质链长 (Seq. Len.) 过滤。
  7. 按 实验方法 (Experiment Method) 过滤。

不同的算法,也有不同的过滤规则,具体可以参考 AlphaFold、ESMFold、UniFold 等相关论文。例如 PolyFold:
PolyFold
PDB 数据库的信息,参考:RCSB PDB 数据集 (2023.8) 的多维度信息统计

以全量 PDB 为例,共有 203657 条数据,即:

  1. 时间 [2021-09-30, 2023-01-01),剩余 15961,过滤 92.1628%。
  2. 过滤单链,剩余 11621,过滤 27.1913%。
  3. 过滤非蛋白,剩余 10416,过滤 10.3692%。
  4. 过滤分辨率,小于 9A,剩余 10325,过滤 0.8737%。
  5. 过滤重复残基,重复率大于等于0.8,剩余 10063,过滤 2.5375%。
  6. 过滤序列长度小于20,剩余 9096,过滤 9.6095%。
  7. 过滤实验方法,保留 XD\SN\EM\EC,剩余 9095,过滤 0.011%。

最终,从多聚体 10416 下降至 9095,保留率 87.32%。

处理脚本命令:

python3 scripts/dataset_generator.py -i data/pdb_base_info_202308.csv -o mydata/dataset/train.csv -b 2021-09-30 -e 2023-01-01

运行日志:

[Info] sample: 203657
[Info] filter [2021-09-30 ~ 2023-01-01): 15961/203657, 92.1628 %
[Info] filter monomer: 11621/15961, 27.1913%
[Info] filter na: 10416/11621, 10.3692%
[Info] filter resolution < 9: 10325/10416, 0.8737%
[Info] filter aa same >= 0.8: 10063/10325, 2.5375%
[Info] filter seq len < 20: 9096/10063, 9.6095%
[Info] filter experiment method (include XD|SN|EM|EC): 9095/9096, 0.011%

源码参考:

#!/usr/bin/env python
# -- coding: utf-8 --
"""
Copyright (c) 2022. All rights reserved.
Created by C. L. Wang on 2023/8/15
"""
import argparse
import ast
import collections
import os
import sys
from pathlib import Path

import pandas as pd

p = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
if p not in sys.path:
    sys.path.append(p)


from myutils.project_utils import sort_dict_by_value
from root_dir import ROOT_DIR, DATA_DIR


class DatasetGenerator(object):
    """
    根据多个条件,筛选构建 PDB 蛋白质结构的数据集
    """
    def __init__(self):
        pass

    @staticmethod
    def filter_release_date(df, date=("2021-09-30", "2023-01-01")):
        """
        筛选发布日期
        """
        df = df.sort_values(by=['release_date'])
        n0 = len(df)
        print(f"[Info] sample: {len(df)}")
        n_df = df.loc[(df['release_date'] >= f"{date[0]}") & (df['release_date'] < f"{date[1]}")]
        n1 = len(n_df)
        print(f"[Info] filter [{date[0]} ~ {date[1]}): {n1}/{n0}, {round(100 - (n1/n0 * 100), 4)} %")
        return n_df

    @staticmethod
    def filter_monomer(df):
        """
        筛选过滤 Monomer,保留 Multimer
        """
        n0 = len(df)
        df_chain_type = df["chain_type"]
        flags = []
        for ct_str in df_chain_type:
            items = ct_str.split(",")
            if len(items) == 1:  # 过滤单链
                flags.append(False)
            else:
                flags.append(True)
        n_df = df.loc[flags]
        n1 = len(n_df)
        print(f"[Info] filter monomer: {n1}/{n0}, {round(100 - (n1/n0 * 100), 4)}%")
        return n_df

    @staticmethod
    def filter_na(df):
        """
        过滤 RNA、DNA,只保留 Protein
        """
        n0 = len(df)
        df_chain_type = df["chain_type"]
        flags = []
        for ct_str in df_chain_type:
            items = ct_str.split(",")
            assert len(items) != 1
            if len(set(items)) != 1:  # 过滤NA
                flags.append(False)
            else:
                flags.append(True)
        n_df = df.loc[flags]
        n1 = len(n_df)
        print(f"[Info] filter na: {n1}/{n0}, {round(100 - (n1/n0 * 100), 4)}%")
        return n_df

    @staticmethod
    def filter_resolution(df, r_val=9):
        """
        过滤低分辨率
        """
        n0 = len(df)
        n_df = df.loc[df["resolution"] < r_val]
        n1 = len(n_df)
        print(f"[Info] filter resolution < 9: {n1}/{n0}, {round(100 - (n1/n0 * 100), 4)}%")
        return n_df

    @staticmethod
    def filter_same_aa(df, thr_ratio=0.8):
        """
        过滤相同氨基酸占比较高
        """
        n0 = len(df)
        df_seq = df["seq"]
        flags = []
        for item_str in df_seq:
            if not isinstance(item_str, str):
                flags.append(False)  # 去掉
                continue
            is_same = False
            items = item_str.split(",")
            for item in items:
                n_item = len(item)
                num_aa_dict = collections.defaultdict(int)
                for aa in item:
                    num_aa_dict[aa] += 1
                num_aa_data = sort_dict_by_value(num_aa_dict, reverse=True)
                v_max = num_aa_data[0][1]
                ratio = v_max / n_item
                if ratio >= thr_ratio:
                    # print(f"[Info] item: {item}")
                    is_same = True
                    break
            if is_same:
                flags.append(False)  # 去掉
            else:
                flags.append(True)

        n_df = df.loc[flags]
        n1 = len(n_df)
        print(f"[Info] filter aa same >= 0.8: {n1}/{n0}, {round(100 - (n1/n0 * 100), 4)}%")
        return n_df

    @staticmethod
    def filter_short_seq_len(df, thr_len=20):
        """
        过滤序列长度角度的蛋白质,Multimer中只要存在1条,即过滤
        """
        n0 = len(df)
        df_seq = df["seq"]
        flags = []
        for item_str in df_seq:
            is_short = False
            items = item_str.split(",")
            for item in items:
                if len(item) < thr_len:
                    is_short = True
                    break
            if is_short:
                flags.append(False)
            else:
                flags.append(True)
        n_df = df.loc[flags]
        n1 = len(n_df)
        print(f"[Info] filter seq len < 20: {n1}/{n0}, {round(100 - (n1/n0 * 100), 4)}%")
        return n_df

    @staticmethod
    def filter_experiment_method(df, method_list=("XD", "SN", "EM", "EC")):
        """
        筛选实验条件,目前保留 ["XD", "SN", "EM", "EC"]
        """
        n0 = len(df)
        experiment_method = df["experiment_method"]
        flags = []
        for ex_item in experiment_method:
            items = ex_item.split(";")
            is_save = False
            for item in items:
                method = item.strip()
                sub_names = method.split(" ")
                sub_m = "".join([i[0].upper() for i in sub_names])
                if sub_m in method_list:
                    is_save = True
                    break
            if is_save:
                flags.append(True)
            else:
                flags.append(False)
        n_df = df.loc[flags]
        n1 = len(n_df)
        print(f"[Info] filter experiment method (include XD|SN|EM|EC): "
              f"{n1}/{n0}, {round(100 - (n1/n0 * 100), 4)}%")
        return n_df

    def filer_pipeline(self, df, date):
        """
        过滤的全部流程
        """
        # 1. 时间筛选
        df = self.filter_release_date(df, date=date)

        # 2. 过滤单链
        df = self.filter_monomer(df)

        # 3. 过滤非蛋白
        df = self.filter_na(df)

        # 4. 分辨率 < 9A
        df = self.filter_resolution(df)

        # 5. 单个氨基酸占比小于 80%
        df = self.filter_same_aa(df)

        # 6. 过滤链长 < 20
        df = self.filter_short_seq_len(df)

        # 7. 实验方法包括 X-ray Diffraction、Electron Microscopy、Solution NMR、Solid-state NMR、Electron Crystallography
        df = self.filter_experiment_method(df)

        return df

    def process(self, csv_path, output_file, date_range):
        """
        处理数据集
        """
        assert os.path.isfile(csv_path) and output_file.endswith("csv")
        df = pd.read_csv(csv_path)
        df.info()

        # 复制列
        df = df[["pdb_id", "chain_id", "resolution", "release_date", "seq", "len", "mol", "experiment_method"]].copy()
        df.columns = ["pdb_id", "chain_id", "resolution", "release_date", "seq", "len",
                      "chain_type", "experiment_method"]

        # 对齐 chain_type 数据格式
        def func(x):
            if not isinstance(x, str):
                return "none"
            ct_item = ast.literal_eval(x)
            c_type_list = []
            for item in ct_item:
                c_type = item.strip()
                c_type_list.append(c_type)
            return ",".join(c_type_list)
        df["chain_type"] = df["chain_type"].apply(lambda x: func(x))

        new_df = self.filer_pipeline(df, date=date_range)  # 过滤流
        new_df = new_df.drop('experiment_method', axis=1)  # 去掉
        new_df.to_csv(output_file, index=False)

        # train_df = self.filer_pipeline(df, date=("2021-09-30", "2023-01-01"))  # 过滤流
        # train_df = train_df.drop('experiment_method', axis=1)
        # train_df.to_csv(os.path.join(output_dir, "train.csv"), index=False)

        # val_df = self.filer_pipeline(df, date=("2023-01-01", "2025-01-01"))  # 过滤流
        # val_df = val_df.drop('experiment_method', axis=1)
        # val_df.to_csv(os.path.join(output_dir, "val.csv"), index=False)

        print("[Info] over!")

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "-i",
        "--input-file",
        help="the input file of pdb database profile.",
        type=Path,
        required=True,
    )
    parser.add_argument(
        "-o",
        "--output-file",
        help="the output file of result csv.",
        type=Path,
        required=True
    )
    parser.add_argument(
        "-b",
        "--begin-date",
        help="the begin date of pdb db, i.e. 2021-09-30 .",
        type=str,
        required=True
    )
    parser.add_argument(
        "-e",
        "--end-date",
        help="the end date of pdb db, i.e. 2023-01-01 , default 2999-12-31 .",
        type=str,
        default="2999-12-31"
    )

    args = parser.parse_args()

    input_file = str(args.input_file)
    output_file = str(args.output_file)
    begin_date = str(args.begin_date)
    end_date = str(args.end_date)
    date_range = (begin_date, end_date)
    assert os.path.isfile(input_file)

    dg = DatasetGenerator()
    # input_file = os.path.join(ROOT_DIR, "data", "pdb_base_info_202308.csv")
    # output_file = os.path.join(DATA_DIR, "dataset", "train.csv")
    # date_range = ("2021-09-30", "2023-01-01")
    # date_range = ("2023-01-01", "2025-01-01")  # val
    dg.process(input_file, output_file, date_range)


if __name__ == '__main__':
    main()

参考

  • StackOverflow - Filtering Pandas DataFrames on dates
  • Ways to filter Pandas DataFrame by column values
  • pandas.DataFrame.sort_values
  • StackOverflow - Renaming column names in Pandas
  • Pandas: How to Create New DataFrame from Existing DataFrame
  • Export Pandas to CSV without Index & Header
  • StackOverflow - Delete a column from a Pandas DataFrame

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/883223.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机器学习深度学习——机器翻译(序列生成策略)

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位即将上大四&#xff0c;正专攻机器学习的保研er &#x1f30c;上期文章&#xff1a;机器学习&&深度学习——seq2seq实现机器翻译&#xff08;详细实现与原理推导&#xff09; &#x1f4da;订阅专栏&#xff1a;机…

卡车盲区监测+360全景

一、背景分析 1.AI视觉智能终端的ADAS主动防撞告警、DMS驾驶员异常行为告警功能。通过摄像头和人工智能算法对前方车辆、车道、交通场景进行检测识别&#xff0c;再结合对车辆运动状态和驾驶员行为的分析&#xff0c;有效预测ADAS前车碰撞、车道偏离等危险&#xff0c;并对DMS…

pytorch3d成功安装

一、pytorch3d是什么&#xff1f; PyTorch3D的目标是帮助加速深度学习和3D交叉点的研究。3D数据比2D图像更复杂&#xff0c;在从事Mesh R-CNN和C3DPO等项目时&#xff0c;我们遇到了一些挑战&#xff0c;包括3D数据表示、批处理和速度。我们开发了许多有用的算子和抽象&#xf…

好用画流程图软件推荐 excalidraw

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;蚂蚁集团高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《EffectiveJava》独家解析》专栏作者。 热门文章推荐…

《Zookeeper》源码分析(十一)之选举通信网络辅助类

目录 Listener数据结构构造函数run() ListenerHandler数据结构run() SendWorker数据结构构造函数run() RecvWorker数据结构run() Listener Listener用于管理服务器的选举端口。 数据结构 构造函数 run() Listener的主要工作是创建一系列的ListenerHandler并将他们投放到线程池…

无线充电底座

<项目>无线充电器 前言 个人DIY的无线充电底座&#xff08;带磁吸&#xff09;&#xff0c;基于IP6829方案。 Drawn By:67373 硬件部分 3D模型 资料开源链接 https://github.com/linggan17/WirelessCharge

03-循环和关系表达式

循环和关系表达式 5.1、for循环 例子 // forloop.cpp -- introducing the for loop #include <iostream> int main() {using namespace std;int i; // create a counter // initialize; test ; updatefor (i 0; i < 5; i)cout << "C knows loops.\n…

从零开始学习VBA(一)

前置配置设置 首先配置开发设置&#xff08;不同版本的配置方法会有差异&#xff0c;可根据自己使用的EXCEL版本到网络上找对应的方法&#xff0c;比如直接搜索Excel2010 开发工具&#xff09; 以下为excel2016配置方法&#xff1a; 操作路径&#xff1a;文件-选项-自定义功…

1269. 停在原地的方案数

链接&#xff1a; ​​​​​​1269. 停在原地的方案数 题解&#xff1a;坐标型动态规划 class Solution { public:int numWays(int steps, int arrLen) {if (arrLen < 0) {return 0;}// 因为需要返回到0下标位置所以&#xff0c;最远也就是一半int len std::min(steps/…

【福建事业单位-公共基础-】01哲学基本概述和唯物论

【福建事业单位-公共基础-】01哲学基本概述和唯物论 一、哲学基本概述二、辩证唯物论&#xff08;1题&#xff09; 相关考点 一、哲学基本概述 向导、导向、指导&#xff0c;都是中性词&#xff0c;都可以&#xff1b;但是先导是褒义词&#xff0c;要跟上真正的哲学&#xff1…

免费Scrum敏捷开发工具管理敏捷项目

Scrum中非常强调公开、透明、直接有效的沟通&#xff0c;这也是“可视化的管理工具”在敏捷开发中如此重要的原因之一。通过“可视化的管理工具”让所有人直观的看到需求&#xff0c;故事&#xff0c;任务之间的流转状态&#xff0c;可以使团队成员更加快速适应敏捷开发流程。 …

YOLOv5算法改进(1)— 如何去改进YOLOv5算法

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。YOLOv5基础知识入门系列、YOLOv5源码中的参数超详细解析系列和YOLOv5入门实践系列学习完成之后&#xff0c;接着就进入YOLOv5进阶改进算法系列了。&#x1f389;为了让大家能够清楚地了解如何去改进YOLOv5算法以及从哪几方…

【Visual Studio Code】--- Win11 配置 VS Code 为中文 超详细

Win11 配置 VS Code 为中文 超详细 一、概述二、重要提示二、配置 VS Code 为中文 一、概述 一个好的文章能够帮助开发者完成更便捷、更快速的开发。书山有路勤为径&#xff0c;学海无涯苦作舟。我是秋知叶i、期望每一个阅读了我的文章的开发者都能够有所成长。 二、重要提示…

【数理知识】向量的坐标基表示法,Matlab 代码验证

序号内容1【数理知识】向量的坐标基表示法&#xff0c;Matlab 代码验证2【数理知识】向量与基的内积&#xff0c;Matlab 代码验证 文章目录 1. 向量的坐标基表示2. 二维平面向量举例3. Matlab 代码验证Ref 1. 向量的坐标基表示 假设空间中存在一个向量 a ⃗ \vec{a} a &#…

2023讯飞AI开发者大赛-基于可见光图像的柑橘花果梢语义分割挑战赛-初赛记录

初识数据 注册账号后下载数据集 文件目录如下&#xff1a; test中image有75张图片&#xff0c;train中image有225张图&#xff0c;对应json中的225个标注文件&#xff0c;是labelme导出的。训练&#xff1a;测试 遵循3&#xff1a;1原则。 图片分辨率为608*608&#xff1b; …

到江西赣州ibm维修服务器之旅-联想X3850 x6黄灯故障

2023年08月15日&#xff0c;一位江西赣州工厂客户通过朋友介绍与冠峰售前工程师取得联系&#xff0c;双方对产品故障前后原因沟通的大致情况如下&#xff1a; 服务器型号&#xff1a;Lenovo system x3850 x6 为用户公司erp仓库服务器 服务器故障&#xff1a;正常使用过程中业…

YOLOV8改进:加入RCS-OSA模块,提升检测速度

1.该文章属于YOLOV5/YOLOV7/YOLOV8改进专栏,包含大量的改进方式,主要以2023年的最新文章和2022年的文章提出改进方式。 2.提供更加详细的改进方法,如将注意力机制添加到网络的不同位置,便于做实验,也可以当做论文的创新点。 2.涨点效果:RCS-OSA模块更加轻量化,有效提升检…

广联达OA前台sql注入+后台文件上传漏洞复现分析

文章目录 前言资产特征前台sql注入后台文件上传解决办法 前言 最近看到广联达OA的前端sql注入和后端文件上传漏洞联动的poc 广联达科技股份有限公司以建设工程领域专业应用为核心基础支撑&#xff0c;提供一百余款基于“端云大数据”产品/服务&#xff0c;提供产业大数据、产业…

力扣 198. 打家劫舍

题目来源&#xff1a;https://leetcode.cn/problems/house-robber/description/ C题解&#xff1a;因为是间接偷窃&#xff0c;所以偷nums[i]家前&#xff0c;一定偷过第i-2或者i-3家&#xff0c;因为i-1不能偷。 例如12345共5家&#xff0c;先偷第1家&#xff0c;那么2不能偷…

ChatGLM-RLHF(七)-PPO实践(Proximal Policy Optimization)原理实现代码逐行注释

从open AI 的论文可以看到&#xff0c;大语言模型的优化&#xff0c;分下面三个步骤&#xff0c;SFT&#xff0c;RM&#xff0c;PPO&#xff0c;我们跟随大神的步伐&#xff0c;来学习一下这三个步骤和代码实现&#xff0c;本章介绍PPO实践。 生活中&#xff0c;我们经常会遇到…