ゲノムアノテーションファイルとしてGFF形式やGFF形式から派生したGTF形式などがあります。ここではGFF形式の構造について説明し、Pythonによる基本操作を解説します。
動作確認環境
OS
- Windows10 + WSL (WindowsユーザーのためのPythonを用いたゲノム解析環境)
Python
- Python 3.7.6
モジュール
- BCBio-GFF 0.6.6
GFF形式のバージョンとその基本構造
GFF形式の種類
GFF形式にはいくつかのバージョンがあり、現在ではversion2 (GFF2)とversion3 (GFF3)がよく使われています。また、GFF2をもとにした規格としてGTFというものもあります(規格としてはGFF2とGTFは同一)。
ここではGFF形式のうち、特にGFF3形式を扱っていきます。
GFF3形式の構造
GFF3形式はテキスト形式で、1つの行が1つのfeature領域のアノテーションを表します。また先頭が「##」で始まる行にはメタデータ、「#」で始まる行にはコメントが記載されています。なお、NCBIによるGFF3形式では「#!」もメタデータとして扱われていますが、GFF3形式の公式規則ではなくあくまでもNCBIのローカルルールとして運用されています。
例えばGRCh38の21番染色体のゲノムアノテーションを表すGFF3形式は以下のようになります。
アノテーション部分の各行はタブ区切りで左から、
seqid | そのfeature領域を含む染色体のID |
source | アノテーションに用いたソフトウェアやデータベース |
type | feature領域のタイプ(gene, exon, CDS, mRNAなど) |
start | feature領域の開始位置 |
end | feature領域の終了位置 |
score | feature領域の信頼度スコア |
strand | feature領域の遺伝子の向き(プラス鎖 / マイナス鎖) |
phase | typeがCDSの時に、何番目の塩基からコドンが始まるかを表す(0 / 1 / 2) |
attributes | feature領域の属性(tag=valueの形式で表現され、セミコロン区切りで複数の属性を指定可能) |
となります。該当する項目が空欄の場合は「.」で表記されます。
なお、attributesのtagは自由に設定可能ですが、大文字で始まるtagはあらかじめ予約されたtag名となっています。あらかじめ予約されたtagとしては以下のようなものがあります。
ID | feature領域のID |
Name | feature領域の名前 |
Parent | そのfeature領域の親となる領域を表すID |
Note | メモ |
Dbxref | データベースの相互参照 |
Is_circular | そのfeature領域が環状構造であるかどうか |
追加のtagとしては、例えばNCBIによるGFF3形式では「anticodon、description、exception、exon_number、gbkey、gene、gene_biotype、gene_synonym、locus_tag、ncrna_class、part、partial、product、protein_id、pseudo、pseudogene、start_range、end_range、transcript_id、transl_except」などが用意されています。詳細はNCBIのドキュメント(What is GFF3 format?)をご覧ください。
その他、GFF3形式の詳細については以下をご覧ください。
サンプルで用いるGFF3形式ファイル
ここではサンプルとしてヒトのリファレンスゲノム配列(GRCh38)の21番染色体のアノテーションファイルをGFF3形式で取得しましょう。以下のEnsemblのサイトから右側の「Gene annotation」の部分の「Download GTF or GFF3 files for genes, cDNAs, ncRNA, proteins」のGFF3をクリックします。
GRCh38のアノテーションファイルのFTPサイトが表示されるので、このうち21番染色体を表す以下のFTPアドレスからダウンロードしてください。
- ftp://ftp.ensembl.org/pub/release-101/gff3/homo_sapiens/Homo_sapiens.GRCh38.101.chromosome.21.gff3.gz
ここで取得したGFF3形式のファイルはgzip形式で圧縮されているので、7-zipなどの圧縮・解凍アプリを用いて解凍しましょう。
※ Microsoft Storeに登録されているのは公式版ではありませんが、GNU LGPLのライセンスのもとでオープンソースで公開されています。
なお、リファレンスゲノム配列については以下の記事もご参照ください。
PythonでGFF3形式ファイルを扱うモジュール
GFF3形式のファイルはBCBio-GFFモジュールから扱うことができます。なお、BCBio-GFFモジュールは将来的にBiopythonのライブラリに統合される予定となっています。
(BCBio-GFFがBiopythonに統合されたら、以下の内容をアップデートします)
BCBio-GFFモジュールは以下のコマンドでAnacondaからインストール可能です。(bcbio-gff – Anaconda Cloud)
conda install -c bioconda bcbiogff
また、BCBio-GFF以外にもHTSeqモジュールやその他のモジュールを用いてもGFF3形式のファイルを扱うことは可能です。
GFF3形式ファイルの構造を確認する
まずはこれから扱おうとしているGFF3形式ファイルの構造を確認しておきましょう。
GFF3形式のファイルにおける各項目の一覧とそのアノテーション数を表示します。
import pprint
from BCBio.GFF import GFFExaminer
gff_file = 'Homo_sapiens.GRCh38.101.chromosome.21.gff3'
with open(gff_file) as handle:
examiner = GFFExaminer()
pprint.pprint(examiner.parent_child_map(handle))
{'gff_id': {('21',): 35165}, 'gff_source': {('.',): 3463, ('GRCh38',): 1, ('ensembl',): 2247, ('ensembl_havana',): 7513, ('havana',): 19124, ('havana_tagene',): 2730, ('mirbase',): 87}, 'gff_source_type': {('.', 'biological_region'): 3463, ('GRCh38', 'chromosome'): 1, (中略) ('mirbase', 'miRNA'): 29, ('mirbase', 'ncRNA_gene'): 29}, 'gff_type': {('CDS',): 7899, ('V_gene_segment',): 1, ('biological_region',): 3463, ('chromosome',): 1, ('exon',): 16982, ('five_prime_UTR',): 1593, ('gene',): 262, ('lnc_RNA',): 1657, ('mRNA',): 1002, ('miRNA',): 29, ('ncRNA',): 24, ('ncRNA_gene',): 425, ('pseudogene',): 188, ('pseudogenic_transcript',): 188, ('rRNA',): 4, ('snRNA',): 21, ('snoRNA',): 15, ('three_prime_UTR',): 1383, ('unconfirmed_transcript',): 28}}
GFF3形式のアノテーションには親子関係があるので、その親子関係を表示してみます。{親項目 : [子項目1, 子項目2, … ]}で示されています。
import pprint
from BCBio.GFF import GFFExaminer
gff_file = 'Homo_sapiens.GRCh38.101.chromosome.21.gff3'
with open(gff_file) as handle:
examiner = GFFExaminer()
pprint.pprint(examiner.available_limits(handle))
{('ensembl', 'lnc_RNA'): [('ensembl', 'exon')], ('ensembl', 'mRNA'): [('ensembl', 'CDS'), ('ensembl', 'exon'), ('ensembl', 'five_prime_UTR'), ('ensembl', 'three_prime_UTR')], ('ensembl', 'ncRNA'): [('ensembl', 'exon')], ('ensembl', 'ncRNA_gene'): [('ensembl', 'ncRNA'), ('ensembl', 'rRNA'), ('ensembl', 'snRNA'), ('ensembl', 'snoRNA')], (中略) ('havana_tagene', 'ncRNA_gene'): [('havana_tagene', 'lnc_RNA')], ('mirbase', 'miRNA'): [('mirbase', 'exon')], ('mirbase', 'ncRNA_gene'): [('mirbase', 'miRNA')]}
GFF3形式ファイルを読み込む
bcbio-gffモジュールではSeqRecordオブジェクトとしてGFF3形式のファイルを読み込むことができます。読み込まれたGFF3形式のデータはSeqRecordオブジェクトをアイテムとするイテレータとして格納され、1つの染色体(seqid)が1つのSeqRecordオブジェクトに対応します。
SeqRecordオブジェクトの属性とGFF3形式の項目は次のように対応します。
SeqRecordオブジェクトの属性 | GFF3形式の項目 | |
---|---|---|
annotations | ←→ | メタデータ(「##」で始まる行) |
description | ←→ | なし |
dbxrefs | ←→ | なし |
features | ←→ | アノテーション |
id | ←→ | 染色体のID(seqid) |
letter_annotations | ←→ | なし |
name | ←→ | なし |
seq | ←→ |
GFF3形式のアノテーションの本体はSeqRecordオブジェクトのfeatures属性に格納されています。このfeatures属性はSeqFeatureオブジェクトのリストであり、親子関係のあるアノテーションでは最も上位のアノテーションが抽出されて1つのアノテーションが1つのSeqFeatureオブジェクトに変換されます。それより下の階層のアノテーションは上位階層のアノテーションのsub_features属性にSeqFeatureオブジェクトとして格納されています。
SeqFeautreオブジェクトの属性とGFF3形式の項目との関係は以下のようになります。
SeqFeatureオブジェクトの属性 | GFF3形式の項目 | |
---|---|---|
id | ←→ | feature領域のID |
location | ←→ | feature領域の開始位置・終了位置 |
qualifiers | ←→ | feature領域の属性(key, valueの組み合わせ) |
type | ←→ | feature領域のタイプ(gene, exon, CDS, mRNAなど) |
sub_features | ←→ | 1つ下の階層のアノテーション(子アノテーション) |
先ほど取得したサンプルファイルを読み込んで、3番目のアノテーションを表示してみましょう。GFF.parse関数は最も上位の階層のアノテーションを取得し、取得したSeqFeatureオブジェクトはfeature領域のタイプ別に並び替えられます。
from BCBio import GFF
gff_file = 'Homo_sapiens.GRCh38.101.chromosome.21.gff3'
with open(gff_file) as handle:
for record in GFF.parse(handle):
print('メタデータ')
print(record.annotations)
print('染色体番号:' + str(record.id))
print('-----------')
print(record.features[0])
メタデータ {'gff-version': ['3'], 'sequence-region': [('21', 0, 46709983)]} 染色体番号:21 ----------- type: biological_region location: [5020207:5023177] qualifiers: Key: external_name, Value: ['oe = 0.75'] Key: logic_name, Value: ['cpg'] Key: score, Value: ['2.14e+03']
この方法ではGFF形式のアノテーションの親子関係が反映されているので、下位階層の子アノテーションを取得する場合はsub_features属性を使いましょう。
親子関係を無視してすべてのアノテーションを取得する方法としてはGFF.parse関数の引数にtarget_lines=1と指定して、1行ずつ別々のSeqRecordオブジェクトとして取得する方法があります。この場合は1つのSeqRecordオブジェクトに1つのSeqFeatureオブジェクトが含まれており、アノテーションの数だけSeqRecordオブジェクトが生成されます。
from BCBio import GFF
gff_file = 'Homo_sapiens.GRCh38.101.chromosome.21.gff3'
with open(gff_file) as handle:
records = GFF.parse(handle, target_lines=1)
record = next(records)
print('メタデータ')
print(record.annotations)
print('染色体番号:' + str(record.id))
print('-----------')
print(record.features[0])
メタデータ {} 染色体番号:21 ----------- type: chromosome location: [0:46709983] id: chromosome:21 qualifiers: Key: Alias, Value: ['CM000683.2', 'chr21', 'NC_000021.9'] Key: ID, Value: ['chromosome:21'] Key: source, Value: ['GRCh38']
コメント