序列物件

生物序列可以說是生物資訊學中的核心物件,在本章中,我們將介紹 Biopython 處理序列的機制,即 Seq 物件。章節 序列註解物件 將介紹相關的 SeqRecord 物件,它結合了序列資訊和任何註解,並在章節 序列輸入/輸出 中再次用於序列輸入/輸出。

序列本質上是像 AGTACACTGGT 這樣的一串字母,這看起來很自然,因為這是生物檔案格式中最常見的序列呈現方式。

Seq 物件和標準 Python 字串之間最重要的區別在於它們有不同的方法。雖然 Seq 物件支援許多與普通字串相同的方法,但其 translate() 方法透過執行生物轉譯而有所不同,並且還有其他生物相關方法,例如 reverse_complement()

序列的行為類似字串

在大多數情況下,我們可以像處理普通 Python 字串一樣處理 Seq 物件,例如取得長度或疊代元素

>>> from Bio.Seq import Seq
>>> my_seq = Seq("GATCG")
>>> for index, letter in enumerate(my_seq):
...     print("%i %s" % (index, letter))
...
0 G
1 A
2 T
3 C
4 G
>>> print(len(my_seq))
5

你可以像對待字串一樣存取序列的元素(但請記住,Python 從零開始計算!)

>>> print(my_seq[0])  # first letter
G
>>> print(my_seq[2])  # third letter
T
>>> print(my_seq[-1])  # last letter
G

Seq 物件具有 .count() 方法,就像字串一樣。請注意,這表示就像 Python 字串一樣,這會提供一個非重疊的計數

>>> from Bio.Seq import Seq
>>> "AAAA".count("AA")
2
>>> Seq("AAAA").count("AA")
2

對於某些生物應用,你可能實際上需要一個重疊的計數(即在這個簡單的範例中為 \(3\))。當搜尋單個字母時,這不會有任何差異

>>> from Bio.Seq import Seq
>>> my_seq = Seq("GATCGATGGGCCTATATAGGATCGAAAATCGC")
>>> len(my_seq)
32
>>> my_seq.count("G")
9
>>> 100 * (my_seq.count("G") + my_seq.count("C")) / len(my_seq)
46.875

雖然你可以使用上面的程式碼片段來計算 GC%,但請注意,Bio.SeqUtils 模組已經內建了幾個 GC 函數。例如

>>> from Bio.Seq import Seq
>>> from Bio.SeqUtils import gc_fraction
>>> my_seq = Seq("GATCGATGGGCCTATATAGGATCGAAAATCGC")
>>> gc_fraction(my_seq)
0.46875

請注意,使用 Bio.SeqUtils.gc_fraction() 函數應會自動處理大小寫混合的序列和表示 G 或 C 的模糊核苷酸 S。

另請注意,就像普通的 Python 字串一樣,Seq 物件在某些方面是「唯讀」的。如果你需要編輯你的序列,例如模擬點突變,請查看下面討論 MutableSeq 物件的 MutableSeq 物件 區段。

序列切片

更複雜的範例,讓我們取得序列的切片

>>> from Bio.Seq import Seq
>>> my_seq = Seq("GATCGATGGGCCTATATAGGATCGAAAATCGC")
>>> my_seq[4:12]
Seq('GATGGGCC')

請注意,「Seq」物件遵循 Python 字串常用的索引慣例,序列的第一個元素編號為 0。當你執行切片時,會包含第一個項目(在此例中為 4),而排除最後一個項目(在此例中為 12)。

同樣像 Python 字串一樣,你可以執行具有起始、停止和步幅(步長,預設為 1)的切片。例如,我們可以取得這個 DNA 序列的第一、第二和第三個密碼子位置

>>> my_seq[0::3]
Seq('GCTGTAGTAAG')
>>> my_seq[1::3]
Seq('AGGCATGCATC')
>>> my_seq[2::3]
Seq('TAGCTAAGAC')

你可能在 Python 字串中看到的另一個步幅技巧是使用 -1 的步幅來反轉字串。你也可以對 Seq 物件執行此操作

>>> my_seq[::-1]
Seq('CGCTAAAAGCTAGGATATATCCGGGTAGCTAG')

將 Seq 物件轉換為字串

如果你真的只需要一個普通字串,例如要寫入檔案或插入資料庫,那麼這很容易取得

>>> str(my_seq)
'GATCGATGGGCCTATATAGGATCGAAAATCGC'

由於在 Seq 物件上呼叫 str() 會將完整的序列傳回為字串,因此你通常不必明確地執行此轉換。Python 會在 print 函數中自動執行此操作

>>> print(my_seq)
GATCGATGGGCCTATATAGGATCGAAAATCGC

當使用 Python 字串格式或內插運算子 (%) 時,你也可以將 Seq 物件直接與 %s 佔位符一起使用

>>> fasta_format_string = ">Name\n%s\n" % my_seq
>>> print(fasta_format_string)
>Name
GATCGATGGGCCTATATAGGATCGAAAATCGC

這行程式碼會建構一個簡單的 FASTA 格式記錄(而不必擔心換行)。區段 格式化方法 描述了從 SeqRecord 物件取得 FASTA 格式化字串的簡潔方法,而關於讀取和寫入 FASTA 格式序列檔案的更廣泛主題將在章節 序列輸入/輸出 中涵蓋。

串聯或新增序列

可以透過將兩個 Seq 物件相加來串聯它們

>>> from Bio.Seq import Seq
>>> seq1 = Seq("ACGT")
>>> seq2 = Seq("AACCGG")
>>> seq1 + seq2
Seq('ACGTAACCGG')

Biopython 不會檢查序列內容,並且如果例如你串聯蛋白質序列和 DNA 序列(這很可能是一個錯誤)也不會引發例外狀況

>>> from Bio.Seq import Seq
>>> protein_seq = Seq("EVRNAK")
>>> dna_seq = Seq("ACGT")
>>> protein_seq + dna_seq
Seq('EVRNAKACGT')

你可能經常有許多序列要加在一起,這可以使用像這樣的 for 迴圈來完成

>>> from Bio.Seq import Seq
>>> list_of_seqs = [Seq("ACGT"), Seq("AACC"), Seq("GGTT")]
>>> concatenated = Seq("")
>>> for s in list_of_seqs:
...     concatenated += s
...
>>> concatenated
Seq('ACGTAACCGGTT')

與 Python 字串一樣,Biopython Seq 也具有 .join 方法

>>> from Bio.Seq import Seq
>>> contigs = [Seq("ATG"), Seq("ATCCCG"), Seq("TTGCA")]
>>> spacer = Seq("N" * 10)
>>> spacer.join(contigs)
Seq('ATGNNNNNNNNNNATCCCGNNNNNNNNNNTTGCA')

變更大小寫

Python 字串具有非常有用的 upperlower 方法來變更大小寫。例如,

>>> from Bio.Seq import Seq
>>> dna_seq = Seq("acgtACGT")
>>> dna_seq
Seq('acgtACGT')
>>> dna_seq.upper()
Seq('ACGTACGT')
>>> dna_seq.lower()
Seq('acgtacgt')

這些對於執行不區分大小寫的匹配非常有用

>>> "GTAC" in dna_seq
False
>>> "GTAC" in dna_seq.upper()
True

核苷酸序列與(反向)互補

對於核苷酸序列,你可以使用其內建方法輕鬆取得 Seq 物件的互補或反向互補

>>> from Bio.Seq import Seq
>>> my_seq = Seq("GATCGATGGGCCTATATAGGATCGAAAATCGC")
>>> my_seq
Seq('GATCGATGGGCCTATATAGGATCGAAAATCGC')
>>> my_seq.complement()
Seq('CTAGCTACCCGGATATATCCTAGCTTTTAGCG')
>>> my_seq.reverse_complement()
Seq('GCGATTTTCGATCCTATATAGGCCCATCGATC')

如先前所述,反轉 Seq 物件(或 Python 字串)的簡單方法是以 -1 的步幅對其進行切片

>>> my_seq[::-1]
Seq('CGCTAAAAGCTAGGATATATCCGGGTAGCTAG')

如果你不小心嘗試執行一些奇怪的操作,例如取得蛋白質序列的(反向)互補,則結果在生物學上是沒有意義的

>>> from Bio.Seq import Seq
>>> protein_seq = Seq("EVRNAK")
>>> protein_seq.complement()
Seq('EBYNTM')

這裡的字母「E」不是核苷酸的有效 IUPAC 模糊程式碼,因此未被互補。但是,「V」表示「A」、「C」或「G」且具有互補「B」,依此類推。

區段 將序列檔案轉換為其反向互補 中的範例將 Seq 物件的反向互補方法與 Bio.SeqIO 結合以進行序列輸入/輸出。

轉錄

在討論轉錄之前,我想嘗試釐清鏈的問題。請考慮以下(虛構的)雙鏈 DNA 片段,它編碼一個短肽

\[\begin{split}\begin{gathered} \text{DNA 編碼鏈 (又名 Crick 鏈,鏈 } +1 \text{)} \\ \text{5'} \qquad \texttt{ATGGCCATTGTAATGGGCCGCTGAAAGGGTGCCCGATAG} \qquad \text{3'} \\ \texttt{|||||||||||||||||||||||||||||||||||||||} \\ \text{3'} \qquad \texttt{TACCGGTAACATTACCCGGCGACTTTCCCACGGGCTATC} \qquad \text{5'} \\ \text{DNA 模板鏈 (又名 Watson 鏈,鏈 } -1 \text{)} \end{gathered}\end{split}\]

這個 DNA 序列的轉錄會產生以下 RNA 序列

\[\begin{split}\begin{gathered} \text{5'} \qquad \texttt{AUGGCCAUUGUAAUGGGCCGCUGAAAGGGUGCCCGAUAG} \qquad \text{3'} \\ \text{單鏈信使 RNA} \end{gathered}\end{split}\]

實際的生物轉錄過程從模板鏈開始,執行反向互補(TCAG \(\rightarrow\) CUGA)以產生 mRNA。但是,在 Biopython 和生物資訊學中,我們通常直接處理編碼鏈,因為這表示我們可以只透過切換 T \(\rightarrow\) U 來取得 mRNA 序列。

現在讓我們實際開始在 Biopython 中進行轉錄。首先,讓我們為編碼和模板 DNA 鏈建立 Seq 物件

>>> from Bio.Seq import Seq
>>> coding_dna = Seq("ATGGCCATTGTAATGGGCCGCTGAAAGGGTGCCCGATAG")
>>> coding_dna
Seq('ATGGCCATTGTAATGGGCCGCTGAAAGGGTGCCCGATAG')
>>> template_dna = coding_dna.reverse_complement()
>>> template_dna
Seq('CTATCGGGCACCCTTTCAGCGGCCCATTACAATGGCCAT')

這些應該與上面的圖表相符 - 請記住,按照慣例,核苷酸序列通常從 5' 到 3' 方向讀取,而在圖表中,模板鏈以相反的順序顯示。

現在,讓我們使用 Seq 物件內建的 transcribe 方法,將編碼股轉錄成對應的 mRNA。

>>> coding_dna
Seq('ATGGCCATTGTAATGGGCCGCTGAAAGGGTGCCCGATAG')
>>> messenger_rna = coding_dna.transcribe()
>>> messenger_rna
Seq('AUGGCCAUUGUAAUGGGCCGCUGAAAGGGUGCCCGAUAG')

如你所見,這個方法只是將 T 取代為 U 而已。

如果你想要從模板股開始進行真正的生物轉錄,那麼這將會是一個兩步驟的過程。

>>> template_dna.reverse_complement().transcribe()
Seq('AUGGCCAUUGUAAUGGGCCGCUGAAAGGGUGCCCGAUAG')

Seq 物件也包含一個反轉錄方法,用於從 mRNA 回到 DNA 的編碼股。同樣地,這只是一個簡單的 U \(\rightarrow\) T 取代。

>>> from Bio.Seq import Seq
>>> messenger_rna = Seq("AUGGCCAUUGUAAUGGGCCGCUGAAAGGGUGCCCGAUAG")
>>> messenger_rna
Seq('AUGGCCAUUGUAAUGGGCCGCUGAAAGGGUGCCCGAUAG')
>>> messenger_rna.back_transcribe()
Seq('ATGGCCATTGTAATGGGCCGCTGAAAGGGTGCCCGATAG')

注意: Seq 物件的 transcribeback_transcribe 方法是在 Biopython 1.49 版本中新增的。對於較舊的版本,你必須改用 Bio.Seq 模組中的函式,請參閱直接使用字串 一節。

轉譯

沿用以上轉錄章節討論的相同範例,現在讓我們將這個 mRNA 轉譯成對應的蛋白質序列 – 同樣是利用 Seq 物件的其中一種生物方法。

>>> from Bio.Seq import Seq
>>> messenger_rna = Seq("AUGGCCAUUGUAAUGGGCCGCUGAAAGGGUGCCCGAUAG")
>>> messenger_rna
Seq('AUGGCCAUUGUAAUGGGCCGCUGAAAGGGUGCCCGAUAG')
>>> messenger_rna.translate()
Seq('MAIVMGR*KGAR*')

你也可以直接從編碼股 DNA 序列進行轉譯。

>>> from Bio.Seq import Seq
>>> coding_dna = Seq("ATGGCCATTGTAATGGGCCGCTGAAAGGGTGCCCGATAG")
>>> coding_dna
Seq('ATGGCCATTGTAATGGGCCGCTGAAAGGGTGCCCGATAG')
>>> coding_dna.translate()
Seq('MAIVMGR*KGAR*')

你會注意到在上述的蛋白質序列中,除了末端的停止符號之外,還有一個內部的停止符號。這是有意選擇的範例,因為它可以讓我們討論一些可選的參數,包括不同的轉譯表(遺傳密碼)。

Biopython 中可用的轉譯表是基於 NCBI 的轉譯表(請參閱本教學的下一節)。預設情況下,轉譯將使用標準遺傳密碼(NCBI 表格 ID 1)。假設我們正在處理粒線體序列。我們需要告訴轉譯函式改用相關的遺傳密碼。

>>> coding_dna.translate(table="Vertebrate Mitochondrial")
Seq('MAIVMGRWKGAR*')

你也可以使用較短的 NCBI 表格編號來指定表格,這個編號通常包含在 GenBank 檔案的特徵註解中。

>>> coding_dna.translate(table=2)
Seq('MAIVMGRWKGAR*')

現在,你可能想要將核苷酸轉譯到第一個同框的停止密碼子,然後停止(就像自然界中發生的情況一樣)。

>>> coding_dna.translate()
Seq('MAIVMGR*KGAR*')
>>> coding_dna.translate(to_stop=True)
Seq('MAIVMGR')
>>> coding_dna.translate(table=2)
Seq('MAIVMGRWKGAR*')
>>> coding_dna.translate(table=2, to_stop=True)
Seq('MAIVMGRWKGAR')

請注意,當你使用 to_stop 參數時,停止密碼子本身不會被轉譯 – 且停止符號不會包含在你的蛋白質序列的末端。

你甚至可以指定停止符號,如果你不喜歡預設的星號的話。

>>> coding_dna.translate(table=2, stop_symbol="@")
Seq('MAIVMGRWKGAR@')

現在,假設你有一個完整的編碼序列 CDS,也就是說,一個核苷酸序列(例如 mRNA – 在任何剪接之後),其長度是密碼子的整數倍(也就是說,長度是三的倍數),以起始密碼子開始,以停止密碼子結束,並且沒有內部的同框停止密碼子。一般來說,給定一個完整的 CDS,預設的轉譯方法會執行你想要的操作(也許會使用 to_stop 選項)。但是,如果你的序列使用非標準的起始密碼子怎麼辦?這在細菌中很常見 – 例如,大腸桿菌 K12 中的 yaaX 基因。

>>> from Bio.Seq import Seq
>>> gene = Seq(
...     "GTGAAAAAGATGCAATCTATCGTACTCGCACTTTCCCTGGTTCTGGTCGCTCCCATGGCA"
...     "GCACAGGCTGCGGAAATTACGTTAGTCCCGTCAGTAAAATTACAGATAGGCGATCGTGAT"
...     "AATCGTGGCTATTACTGGGATGGAGGTCACTGGCGCGACCACGGCTGGTGGAAACAACAT"
...     "TATGAATGGCGAGGCAATCGCTGGCACCTACACGGACCGCCGCCACCGCCGCGCCACCAT"
...     "AAGAAAGCTCCTCATGATCATCACGGCGGTCATGGTCCAGGCAAACATCACCGCTAA"
... )
>>> gene.translate(table="Bacterial")
Seq('VKKMQSIVLALSLVLVAPMAAQAAEITLVPSVKLQIGDRDNRGYYWDGGHWRDH...HR*',
ProteinAlpabet())
>>> gene.translate(table="Bacterial", to_stop=True)
Seq('VKKMQSIVLALSLVLVAPMAAQAAEITLVPSVKLQIGDRDNRGYYWDGGHWRDH...HHR')

在細菌遺傳密碼中,GTG 是一個有效的起始密碼子,雖然它通常會編碼纈胺酸,但如果用作起始密碼子,它應該轉譯為甲硫胺酸。如果你告訴 Biopython 你的序列是一個完整的 CDS,就會發生這種情況。

>>> gene.translate(table="Bacterial", cds=True)
Seq('MKKMQSIVLALSLVLVAPMAAQAAEITLVPSVKLQIGDRDNRGYYWDGGHWRDH...HHR')

除了告訴 Biopython 將替代的起始密碼子轉譯為甲硫胺酸之外,使用這個選項還可以確保你的序列確實是一個有效的 CDS(如果不是,你會得到一個例外)。

轉譯 CDS 項目的 FASTA 檔案 一節中的範例結合了 Seq 物件的轉譯方法與 Bio.SeqIO 進行序列輸入/輸出。

轉譯表

在前面的章節中,我們討論了 Seq 物件的轉譯方法(並提到了 Bio.Seq 模組中的等效函式 – 請參閱直接使用字串 一節)。這些方法在內部使用了從 NCBI 資訊(位於 ftp://ftp.ncbi.nlm.nih.gov/entrez/misc/data/gc.prt)衍生的密碼子表物件,這些資訊也顯示在 https://www.ncbi.nlm.nih.gov/Taxonomy/Utils/wprintgc.cgi 上,其版面配置更易於閱讀。

如同之前,讓我們只關注兩個選擇:標準轉譯表和脊椎動物粒線體 DNA 的轉譯表。

>>> from Bio.Data import CodonTable
>>> standard_table = CodonTable.unambiguous_dna_by_name["Standard"]
>>> mito_table = CodonTable.unambiguous_dna_by_name["Vertebrate Mitochondrial"]

或者,這些表格分別使用 ID 編號 1 和 2 來標記。

>>> from Bio.Data import CodonTable
>>> standard_table = CodonTable.unambiguous_dna_by_id[1]
>>> mito_table = CodonTable.unambiguous_dna_by_id[2]

你可以透過列印這些表格來比較實際的表格內容。

>>> print(standard_table)
Table 1 Standard, SGC0

  |  T      |  C      |  A      |  G      |
--+---------+---------+---------+---------+--
T | TTT F   | TCT S   | TAT Y   | TGT C   | T
T | TTC F   | TCC S   | TAC Y   | TGC C   | C
T | TTA L   | TCA S   | TAA Stop| TGA Stop| A
T | TTG L(s)| TCG S   | TAG Stop| TGG W   | G
--+---------+---------+---------+---------+--
C | CTT L   | CCT P   | CAT H   | CGT R   | T
C | CTC L   | CCC P   | CAC H   | CGC R   | C
C | CTA L   | CCA P   | CAA Q   | CGA R   | A
C | CTG L(s)| CCG P   | CAG Q   | CGG R   | G
--+---------+---------+---------+---------+--
A | ATT I   | ACT T   | AAT N   | AGT S   | T
A | ATC I   | ACC T   | AAC N   | AGC S   | C
A | ATA I   | ACA T   | AAA K   | AGA R   | A
A | ATG M(s)| ACG T   | AAG K   | AGG R   | G
--+---------+---------+---------+---------+--
G | GTT V   | GCT A   | GAT D   | GGT G   | T
G | GTC V   | GCC A   | GAC D   | GGC G   | C
G | GTA V   | GCA A   | GAA E   | GGA G   | A
G | GTG V   | GCG A   | GAG E   | GGG G   | G
--+---------+---------+---------+---------+--

>>> print(mito_table)
Table 2 Vertebrate Mitochondrial, SGC1

  |  T      |  C      |  A      |  G      |
--+---------+---------+---------+---------+--
T | TTT F   | TCT S   | TAT Y   | TGT C   | T
T | TTC F   | TCC S   | TAC Y   | TGC C   | C
T | TTA L   | TCA S   | TAA Stop| TGA W   | A
T | TTG L   | TCG S   | TAG Stop| TGG W   | G
--+---------+---------+---------+---------+--
C | CTT L   | CCT P   | CAT H   | CGT R   | T
C | CTC L   | CCC P   | CAC H   | CGC R   | C
C | CTA L   | CCA P   | CAA Q   | CGA R   | A
C | CTG L   | CCG P   | CAG Q   | CGG R   | G
--+---------+---------+---------+---------+--
A | ATT I(s)| ACT T   | AAT N   | AGT S   | T
A | ATC I(s)| ACC T   | AAC N   | AGC S   | C
A | ATA M(s)| ACA T   | AAA K   | AGA Stop| A
A | ATG M(s)| ACG T   | AAG K   | AGG Stop| G
--+---------+---------+---------+---------+--
G | GTT V   | GCT A   | GAT D   | GGT G   | T
G | GTC V   | GCC A   | GAC D   | GGC G   | C
G | GTA V   | GCA A   | GAA E   | GGA G   | A
G | GTG V(s)| GCG A   | GAG E   | GGG G   | G
--+---------+---------+---------+---------+--

你可能會發現以下屬性很有用 – 例如,如果你嘗試自行進行基因搜尋的話。

>>> mito_table.stop_codons
['TAA', 'TAG', 'AGA', 'AGG']
>>> mito_table.start_codons
['ATT', 'ATC', 'ATA', 'ATG', 'GTG']
>>> mito_table.forward_table["ACG"]
'T'

比較 Seq 物件

序列比較實際上是一個非常複雜的主題,而且沒有簡單的方法可以判斷兩個序列是否相等。基本問題在於序列中字母的意義取決於上下文 – 字母「A」可能是 DNA、RNA 或蛋白質序列的一部分。Biopython 可以追蹤分子類型,因此比較兩個 Seq 物件也可能意味著要考慮這一點。

DNA 片段「ACG」和 RNA 片段「ACG」應該相等嗎?那胜肽「ACG」呢?或是 Python 字串「ACG」呢?在日常使用中,你的序列通常都會是相同的類型(全部是 DNA、全部是 RNA 或全部是蛋白質)。好吧,從 Biopython 1.65 版本開始,序列比較只會查看序列並像 Python 字串一樣進行比較。

>>> from Bio.Seq import Seq
>>> seq1 = Seq("ACGT")
>>> "ACGT" == seq1
True
>>> seq1 == "ACGT"
True

作為這個觀念的延伸,在 Python 字典中使用序列物件作為鍵等同於使用該序列作為鍵的純字串。另請參閱 將 Seq 物件轉換為字串 一節。

具有未知序列內容的序列

在某些情況下,序列的長度可能是已知的,但構成它的實際字母卻未知。例如,GenBank 和 EMBL 檔案可能只透過其組態資訊來表示基因組 DNA 序列,而沒有明確指定序列內容。此類序列可以使用參數 None 建立 Seq 物件來表示,後面接著序列長度。

>>> from Bio.Seq import Seq
>>> unknown_seq = Seq(None, 10)

因此建立的 Seq 物件具有明確定義的長度。然而,任何嘗試存取序列內容的動作都會引發 UndefinedSequenceError

>>> unknown_seq
Seq(None, length=10)
>>> len(unknown_seq)
10
>>> print(unknown_seq)
Traceback (most recent call last):
...
Bio.Seq.UndefinedSequenceError: Sequence content is undefined
>>>

具有部分定義序列內容的序列

有時,序列內容僅針對部分序列定義,而在其他地方則未定義。例如,以下 MAF(多重比對格式)檔案的摘錄顯示了人類、黑猩猩、獼猴、小鼠、大鼠、狗和負鼠基因組序列的比對。

s hg38.chr7     117512683 36 + 159345973 TTGAAAACCTGAATGTGAGAGTCAGTCAAGGATAGT
s panTro4.chr7  119000876 36 + 161824586 TTGAAAACCTGAATGTGAGAGTCACTCAAGGATAGT
s rheMac3.chr3  156330991 36 + 198365852 CTGAAATCCTGAATGTGAGAGTCAATCAAGGATGGT
s mm10.chr6      18207101 36 + 149736546 CTGAAAACCTAAGTAGGAGAATCAACTAAGGATAAT
s rn5.chr4       42326848 36 + 248343840 CTGAAAACCTAAGTAGGAGAGACAGTTAAAGATAAT
s canFam3.chr14  56325207 36 +  60966679 TTGAAAAACTGATTATTAGAGTCAATTAAGGATAGT
s monDom5.chr8  173163865 36 + 312544902 TTAAGAAACTGGAAATGAGGGTTGAATGACAAACTT

在每一列中,第一個數字表示染色體上比對序列的起始位置(以零為基底的座標),後接比對序列的大小、股、完整染色體的大小以及比對序列。

可以使用字典來建立表示此類部分定義序列的 Seq 物件,其中字典的 data 參數的鍵是已知序列片段的起始座標,而值則是對應的序列內容。例如,對於第一個序列,我們會使用

>>> from Bio.Seq import Seq
>>> seq = Seq({117512683: "TTGAAAACCTGAATGTGAGAGTCAGTCAAGGATAGT"}, length=159345973)

從部分定義的序列中擷取子序列可能會傳回完全定義的序列、未定義的序列或部分定義的序列,具體取決於座標。

>>> seq[1000:1020]
Seq(None, length=20)
>>> seq[117512690:117512700]
Seq('CCTGAATGTG')
>>> seq[117512670:117512690]
Seq({13: 'TTGAAAA'}, length=20)
>>> seq[117512700:]
Seq({0: 'AGAGTCAGTCAAGGATAGT'}, length=41833273)

如果至少有一個序列是部分或完全未定義的,也可以透過附加序列來建立部分定義的序列。

>>> seq = Seq("ACGT")
>>> undefined_seq = Seq(None, length=10)
>>> seq + undefined_seq + seq
Seq({0: 'ACGT', 14: 'ACGT'}, length=18)

MutableSeq 物件

就像一般的 Python 字串一樣,Seq 物件是「唯讀」的,或者用 Python 的術語來說,是不可變的。除了希望 Seq 物件像字串一樣運作之外,這也是一個有用的預設值,因為在許多生物應用程式中,你會希望確保你沒有變更你的序列資料。

>>> from Bio.Seq import Seq
>>> my_seq = Seq("GCCATTGTAATGGGCCGCTGAAAGGGTGCCCGA")

請觀察如果你嘗試編輯序列會發生什麼事。

>>> my_seq[5] = "G"
Traceback (most recent call last):
...
TypeError: 'Seq' object does not support item assignment

但是,你可以將其轉換為可變序列(MutableSeq 物件),並對其執行幾乎任何你想做的操作。

>>> from Bio.Seq import MutableSeq
>>> mutable_seq = MutableSeq(my_seq)
>>> mutable_seq
MutableSeq('GCCATTGTAATGGGCCGCTGAAAGGGTGCCCGA')

或者,你可以直接從字串建立 MutableSeq 物件。

>>> from Bio.Seq import MutableSeq
>>> mutable_seq = MutableSeq("GCCATTGTAATGGGCCGCTGAAAGGGTGCCCGA")

無論哪種方式,你都會得到一個可以變更的序列物件。

>>> mutable_seq
MutableSeq('GCCATTGTAATGGGCCGCTGAAAGGGTGCCCGA')
>>> mutable_seq[5] = "C"
>>> mutable_seq
MutableSeq('GCCATCGTAATGGGCCGCTGAAAGGGTGCCCGA')
>>> mutable_seq.remove("T")
>>> mutable_seq
MutableSeq('GCCACGTAATGGGCCGCTGAAAGGGTGCCCGA')
>>> mutable_seq.reverse()
>>> mutable_seq
MutableSeq('AGCCCGTGGGAAAGTCGCCGGGTAATGCACCG')

請注意,MutableSeq 物件的 reverse() 方法,就像 Python 清單的 reverse() 方法一樣,會就地反轉序列。

Python 中可變和不可變物件之間的一個重要的技術差異意味著你不能使用 MutableSeq 物件作為字典的鍵,但你可以使用 Python 字串或 Seq 物件來做到這點。

一旦你完成編輯 MutableSeq 物件,如果你需要,可以很容易地回到唯讀的 Seq 物件。

>>> from Bio.Seq import Seq
>>> new_seq = Seq(mutable_seq)
>>> new_seq
Seq('AGCCCGTGGGAAAGTCGCCGGGTAATGCACCG')

你也可以像從 Seq 物件一樣,從 MutableSeq 物件取得字串(將 Seq 物件轉換為字串 一節)。

尋找子序列

序列物件具有 findrfindindexrindex 方法,這些方法的作用與純字串物件上的對應方法相同。唯一的區別在於子序列可以是字串 (str)、bytesbytearraySeqMutableSeq 物件。

>>> from Bio.Seq import Seq, MutableSeq
>>> seq = Seq("GCCATTGTAATGGGCCGCTGAAAGGGTGCCCGA")
>>> seq.index("ATGGGCCGC")
9
>>> seq.index(b"ATGGGCCGC")
9
>>> seq.index(bytearray(b"ATGGGCCGC"))
9
>>> seq.index(Seq("ATGGGCCGC"))
9
>>> seq.index(MutableSeq("ATGGGCCGC"))
9

如果找不到子序列,則會引發 ValueError

>>> seq.index("ACTG")  
Traceback (most recent call last):
...
ValueError: ...

而如果找不到子序列,find 方法則會傳回 -1。

>>> seq.find("ACTG")
-1

rfindrindex 方法會從序列的右側開始搜尋子序列。

>>> seq.find("CC")
1
>>> seq.rfind("CC")
29

使用 search 方法同時搜尋多個子序列。此方法會傳回一個迭代器。

>>> for index, sub in seq.search(["CC", "GGG", "CC"]):
...     print(index, sub)
...
1 CC
11 GGG
14 CC
23 GGG
28 CC
29 CC

search 方法也會將純字串、bytesbytearraySeqMutableSeq 物件作為子序列;相同的子序列只會回報一次,如上面的範例所示。

直接使用字串

為了結束本章,對於那些真的不想使用序列物件(或者偏好函數式編程風格而非物件導向風格)的人,Bio.Seq 模組層級的函式可以接受純 Python 字串、Seq 物件或 MutableSeq 物件。

>>> from Bio.Seq import reverse_complement, transcribe, back_transcribe, translate
>>> my_string = "GCTGTTATGGGTCGTTGGAAGGGTGGTCGTGCTGCTGGTTAG"
>>> reverse_complement(my_string)
'CTAACCAGCAGCACGACCACCCTTCCAACGACCCATAACAGC'
>>> transcribe(my_string)
'GCUGUUAUGGGUCGUUGGAAGGGUGGUCGUGCUGCUGGUUAG'
>>> back_transcribe(my_string)
'GCTGTTATGGGTCGTTGGAAGGGTGGTCGTGCTGCTGGTTAG'
>>> translate(my_string)
'AVMGRWKGGRAAG*'

然而,我們鼓勵您預設使用 Seq 物件。