0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

大学院生の構造生物学はじめまして①

0
Posted at

全国のタンパク質研究マスター達へ

大学院生諸氏が効率よく学習し、修了にたる成果をだすために有用なツールを提案したい。
タンパク質研究マスター(修士課程学生)達だけでなく、是非、タンパク質研究マスター(熟練者)達にもご意見いただければ幸いである。

あなたの研究対象はどんな分子ですか?

構造生物学だけでなく、合成生物学、計算化学においてタンパク質分子を研究対象とする場合がある。大学院では、仮に教授に強制的に決められた研究対象であっても、「あなたの」研究対象と捉えられる。なんとか愛着を持ってほしい。
そのために本記事では、UniprotとProtein Data Bank(PDB)の登録情報から、論文を収集するツールを紹介する。

Google Colabを使ってみよう。

タンパク質分子の情報は、UniprotやPDBというデータベースにまとめられている。
簡単にこれを収集し解析する手法としてgoogle colabを使った手法をおすすめしたい。昨今のchatGPTやgeminiなどの精度向上は凄まじく、慣れればとても有用である。

  1. googleアカウント作成
  2. google colabにログイン
  3. ノートブックを新規作成をクリック
    image.png
    4.コードを順に入れていく。
    image.png
!pip install biopython requests

import requests
import os
from Bio.PDB import PDBList
from Bio.PDB.MMCIF2Dict import MMCIF2Dict

def get_pdb_ids_from_uniprot(query: str) -> list:
    url = "https://rest.uniprot.org/uniprotkb/search"
    params = {"query": query, "format": "json"}
    print(f"UniProtで '{query}' を検索中...")
    
    try:
        response = requests.get(url, params=params)
        response.raise_for_status() 
        result = response.json()
    except requests.exceptions.RequestException as e:
        print(f"APIリクエストエラー: {e}")
        return []

    if not result.get('results'):
        print("検索結果が見つかりませんでした。")
        return []

    first_hit = result['results'][0]
    accession = first_hit.get("primaryAccession", "Unknown")
    print(f"トップヒット Accession: {accession}")

    cross_refs = first_hit.get('uniProtKBCrossReferences', [])
    pdb_ids = [ref['id'] for ref in cross_refs if ref['database'] == "PDB"]
    print(f"関連するPDB IDが {len(pdb_ids)} 件見つかりました。\n")
    
    return pdb_ids

def download_pdb_files(pdb_ids: list, download_dir: str):
    if not pdb_ids:
        return
    os.makedirs(download_dir, exist_ok=True)
    pdbl = PDBList()
    print(f"=== {download_dir} にmmCIFファイルをダウンロードします ===")
    pdbl.download_pdb_files(pdb_ids, pdir=download_dir, file_format="mmCif", overwrite=True)
    print("ダウンロード完了。\n")

def extract_mmcif_metadata(pdb_ids: list, download_dir: str, output_filename: str = "protein_data.tsv"):
    print("=== 構造メタデータの抽出とファイル保存 ===")
    
    output_filepath = os.path.join(download_dir, output_filename)
    
    with open(output_filepath, mode="w", encoding="utf-8") as f:
        f.write("PDB_ID\tDate\tOrganism\tTitle\tMethod\tResolution\tProteins\tLigands\tDOI\n")
        
        for pdb_id in pdb_ids:
            filename = f"{pdb_id.lower()}.cif"
            filepath = os.path.join(download_dir, filename)

            if not os.path.exists(filepath):
                print(f"ファイルが見つかりません: {filepath}")
                continue

            try:
                mmcif_dict = MMCIF2Dict(filepath)
                
                # 基本データの抽出
                title = mmcif_dict.get("_struct.title", ["Unknown"])[0]
                method = mmcif_dict.get("_exptl.method", ["Unknown"])[0]
                resolution = mmcif_dict.get("_reflns.d_resolution_high", ["N/A"])[0]
                doi = mmcif_dict.get("_citation.pdbx_database_id_DOI", ["N/A"])[0]

                # 登録日(Deposition Date)の抽出
                dep_date = mmcif_dict.get("_pdbx_database_status.recvd_initial_deposition_date", ["Unknown"])[0]

                # 由来生物種(Organism)の抽出
                # 天然由来と組換え発現の両方の項目を取得
                org_nat = mmcif_dict.get("_entity_src_nat.pdbx_organism_scientific", [])
                if isinstance(org_nat, str): org_nat = [org_nat]
                
                org_gen = mmcif_dict.get("_entity_src_gen.pdbx_gene_src_scientific_name", [])
                if isinstance(org_gen, str): org_gen = [org_gen]

                # 両方を結合し、mmCIF特有の「?(データなし)」を弾いて重複をなくす
                clean_orgs = [o for o in (org_nat + org_gen) if o and o not in ["?", "Unknown"]]
                organism = ", ".join(set(clean_orgs)) if clean_orgs else "Unknown"

                # タンパク質名の抽出(水分子除外)
                proteins_raw = mmcif_dict.get("_entity.pdbx_description", [])
                if isinstance(proteins_raw, str): proteins_raw = [proteins_raw]
                clean_proteins = [p.replace('\n', ' ').replace('\r', '') for p in proteins_raw if p.lower() not in ["water", "hoh", "h2o"]]
                proteins = ", ".join(set(clean_proteins)) if clean_proteins else "Unknown"

                # リガンド名の抽出(水分子除外)
                ligands_raw = mmcif_dict.get("_pdbx_entity_nonpoly.name", [])
                if isinstance(ligands_raw, str): ligands_raw = [ligands_raw]
                clean_ligands = [l.replace('\n', ' ').replace('\r', '') for l in ligands_raw if l.lower() not in ["water", "hoh", "h2o"]]
                ligands = ", ".join(clean_ligands) if clean_ligands else ""

                print(f"[{pdb_id.upper()}]")
                print(f"  登録日    : {dep_date}")
                print(f"  生物種    : {organism}")
                print(f"  タイトル  : {title}")
                print(f"  手法      : {method}")
                print(f"  分解能    : {resolution} Å")
                print(f"  タンパク質: {proteins}")
                print(f"  リガンド  : {ligands if ligands else 'なし'}")
                print("-" * 40)

                clean_title = title.replace('\n', ' ').replace('\r', '')
                f.write(f"{pdb_id.upper()}\t{dep_date}\t{organism}\t{clean_title}\t{method}\t{resolution}\t{proteins}\t{ligands}\t{doi}\n")

            except Exception as e:
                print(f"{pdb_id} のパース中にエラーが発生しました: {e}")
                
    print(f"\n★抽出結果をテキストファイル '{output_filepath}' に保存しました。")

# ==========================================
# メインの実行ブロック
# ==========================================
if __name__ == "__main__":
    target_name = input("検索したい「タンパク質の名前&&種名」を入力してください (例: FOXP3&&human): ")
    
    safe_folder_name = target_name.replace("&&", "_").replace(" ", "_")
    download_directory = f"./pdb_files/{safe_folder_name}"

    pdb_list = get_pdb_ids_from_uniprot(target_name)

    if pdb_list:
        download_pdb_files(pdb_list, download_dir=download_directory)
        extract_mmcif_metadata(pdb_list, download_dir=download_directory, output_filename="protein_data.tsv")

image.pngこのマークを押すと実行される。

例えば、インプットとして「FOXP3_human」と入れると、色々と出てきた後、
image.png
このように出力される(2026年4月現在)。

ここでは、ヒトのFOXP3というタンパク質分子を検索しており、2つのデータを見つけてきた。
さらに./pdb_files/FOXP3_humanという場所にそのデータが保存されている。
初期画面のうち、タスクバーの上から6つめ、フォルダアイコンをクリックすると、
image.png
このようなタブが出てくる。
image.png

これのうち、📁pdb_filesとなっている箇所をクリックすると、FOXP3_humanというフォルダがあり、ここに検索して得たヒトのFOXP3に関する立体構造のデータがある。
名前はPDB IDとなっている。このmmcifファイルは、pymolなどの分子viewerで美しく可視化することができる。Pymolを使うことができれば、より理解が深まるはずだ。
また、protein_data.tsvというファイルがあり、これはダウンロードしてexcelで開くと、
各PDBファイルの立体構造を扱った論文のDOIが分かる。DOIはそれをそのまま検索すれば大抵その論文にたどり着く。

Google colabを使ったこの仕組みは、PCスペック依存性がとても低いのでおすすめである。
ただしgoogle colabではログアウトするとデータが削除されるため、その点は注意されたし。

文献の調査方法は変わりつつある。

科学論文を投稿することをpublishというが、現在、実際に活版印刷されているのだろうか?
同様に、文献調査も、大学図書館にいって冊子をめくる時代ではない。
僕の時代はggrksと言われたが、現代ではチャッピーに聞いたかと詰められる。
Google colabなどの無料ツールをなるべく使いこなし、是非、大学院での研究を楽しんで欲しい。
また、あらゆる取り組みにおいて、初心者だからといって尻込みする必要はない。今回公開しているコードは、大部分をgeminiが作った。しかしながら、しっかり運用できるものとなっている。はずだ。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?