attTn7 - нуклеотидная последовательность, которая распознается белком TnsD, который является частью бактериальной транспозазы Tn7. При узнавании происходит привлечении дополнительных белков комплекса, которые встраивают транспозон в upstream attTn7 сайта. Такие события происходят с достаточно высокой частотой. Сылка: Target Site Selection by Tn7: attTn7 Transcription and Target Activity
import numpy as np
import requests
import pandas as pd
from scipy.stats import mannwhitneyu
from IPython.display import Image
genes_table = pd.read_csv("human-genes.tsv", sep="\t")
sequences = []
i = 0
req_count = 0
while req_count < 100:
chromosome = genes_table.loc[i, "#chrom"]
start = genes_table.loc[i, "thickStart"]
strand = genes_table.loc[i, "strand"]
i += 1
if str(strand) == "+":
link = f"https://rest.ensembl.org/sequence/region/human/{chromosome}:{start-6}..{start+400}:1?expand_3prime=0;expand_5prime=0"
request = requests.get(link, headers={ "Content-Type" : "text/x-fasta"})
else:
continue
if "error" in request.text:
continue
else:
req_count += 1
sequence = "".join(request.text.split("\n")[1:])
sequences.append(sequence)
with open("sequences.txt", "w") as file:
print(*sequences, sep="\n", file=file)
С использованием кода выше было отобрано 100 генов человека на + цепи для простоты, были взяты участки от -7 нуклкотида от координаты старт-кодона до +400 нуклеотида после. Ссылка на файл
sequences_clear=[]
sequences_test_negative=[]
with open("sequences.txt", "r") as file:
sequences = file.readlines()
for sequence in sequences:
sequence_ = sequence[:13]
if sequence_[7:10] == "ATG":
sequences_clear.append(sequence_)
ATG_coord_fake = sequence[200:].find("ATG")
sequences_test_negative.append(sequence[200:][ATG_coord_fake-7:ATG_coord_fake+6])
sequences_train = sequences_clear[:40]
sequences_test = sequences_clear[40:]
sequences_test_negative = [seq for seq in sequences_test_negative if len(seq) == 13]
sequences_test_negative = sequences_test_negative[:36]
Далее были вырезаны участки размером 13 нуклеотидов в начале генов, из них были отобраны участки, содержащие старт кодон. Полученные последовательности были разделены на 40 для построения PWM, и 36 для теста. Негативный котроль был сформирован из участков вокруг кодонов AUG, удаленных минимум на 200 нуклеотидов от начала гена, таким образом не являющихся старт-кодонами.
class PWM():
def __init__(self, e=1, freq=[0.298, 0.298, 0.202, 0.202]):
self.e = e
self.positions = {"A": 0, "T": 1, "G": 2, "C": 3}
self.frequencies = np.array(freq).reshape((4, 1))
def fit(self, seq_list):
self.seq_arr = np.array(list(map(list, seq_list)), dtype="str")
self.n_pos = len(seq_list[0])
self.n_seq = len(seq_list)
A_n = np.count_nonzero(self.seq_arr == "A", axis=0)
T_n = np.count_nonzero(self.seq_arr == "T", axis=0)
G_n = np.count_nonzero(self.seq_arr == "G", axis=0)
C_n = np.count_nonzero(self.seq_arr == "C", axis=0)
self.matrix = np.stack([A_n, T_n, G_n, C_n], axis=0).astype("float")
pseudocount = self.e / 4
self.matrix += pseudocount
self.matrix = self.matrix / (self.n_seq+self.e)
self.pwm_matrix = np.log(self.matrix / self.frequencies)
def test(self, seq):
weight = 0
for i, nuc in enumerate(list(seq)):
weight += self.pwm_matrix[self.positions[nuc], i]
return weight
def ic_calculate(self):
self.ic_matrix = self.matrix * np.log2(self.matrix / self.frequencies)
def return_pwm(self):
return pd.DataFrame(self.pwm_matrix, columns = np.arange(1, self.n_pos + 1), index = ["A", "T", "G", "C"])
def return_ic(self):
return pd.DataFrame(self.ic_matrix, columns = np.arange(1, self.n_pos + 1), index = ["A", "T", "G", "C"])
PWM была реализована в виде класса с методами для построения PWM, вычисления весов тестовых последовательностей, вычисления матрицы информационного содержания и вывода матриц. Для вычисления базовых частот нуклеотидов был взят GC состав 40.4
pwm = PWM()
pwm.fit(sequences_train)
real_scores = []
fake_scores = []
for seq, fake_seq in zip(sequences_test, sequences_test_negative):
real_scores.append(pwm.test(seq))
fake_scores.append(pwm.test(fake_seq))
pwm.return_pwm()
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
A | -2.279767 | -0.278287 | -0.844682 | -0.670329 | -0.175633 | -0.392697 | -0.521909 | 1.192200 | -3.889205 | -3.889205 | -0.670329 | -0.278287 | -1.691980 |
T | -0.392697 | -0.521909 | -1.324255 | -1.324255 | -1.691980 | -0.844682 | -1.055991 | -3.889205 | 1.192200 | -3.889205 | -0.392697 | -0.278287 | -0.175633 |
G | 0.733728 | 0.213193 | 0.610495 | 0.610495 | 0.894070 | 0.110539 | -0.455856 | -3.500379 | -3.500379 | 1.581026 | 0.610495 | 0.213193 | 0.733728 |
C | 0.542672 | 0.542672 | 0.733728 | 0.674008 | -0.003871 | 0.790081 | 1.074332 | -3.500379 | -3.500379 | -3.500379 | 0.306284 | 0.391441 | 0.306284 |
Матрица была построена на основании полученных ранее последовательностей и протестирована на положительном и отрицательном контроле, оба по 36 последовательностей. Ниже представлен результат непараметрического теста Манна-Уитни наборов полученных весов. Видно, что при уровне значимости 0.05, вес положительного контроля выше веса отрицательного.
print(f"Средний вес положительного контроля: {np.mean(real_scores)}, средний вес отрицательного контроля: {np.mean(fake_scores)}.")
print(mannwhitneyu(real_scores, fake_scores))
Средний вес положительного контроля: 5.708095784373053, средний вес отрицательного контроля: 4.762259673360172. MannwhitneyuResult(statistic=485.0, pvalue=0.03361584398305171)
pwm.ic_calculate()
pwm.return_ic()
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
A | -0.100275 | -0.090578 | -0.156043 | -0.147421 | -0.063346 | -0.113999 | -0.133145 | 1.688518 | -0.034213 | -0.034213 | -0.147421 | -0.090578 | -0.133958 |
T | -0.113999 | -0.133145 | -0.151442 | -0.151442 | -0.133958 | -0.156043 | -0.157921 | -0.034213 | 1.688518 | -0.034213 | -0.113999 | -0.090578 | -0.063346 |
G | 0.445364 | 0.076893 | 0.327599 | 0.327599 | 0.637070 | 0.035979 | -0.084213 | -0.030793 | -0.030793 | 2.239213 | 0.327599 | 0.076893 | 0.445364 |
C | 0.272109 | 0.272109 | 0.445364 | 0.385398 | -0.001124 | 0.507370 | 0.916729 | -0.030793 | -0.030793 | -0.030793 | 0.121246 | 0.168730 | 0.121246 |
Выше представлена матрица информационного содержания для последовательностей, использованных для построения PWM. На рисунке ниже LOGO для этих последовательностей.
Image(filename="logo.png")