Мои PDB ID для РСА 5ZF2, для ЯМР 5ZPV.
Они содержат в себе структуру тиоредоксин подобного белка. Разрешение РСА хорошее 1.98 Å, количество моделей ЯМР: засабмиченных 10, рассчитанных 50.
С помощью команды super структуры из двух экспериментов были сопоставлены для дальнейшего анализа. При этом сразу отметим, что в модели ЯМР аминокислот больше, чем в РСА (106 и 103 соответственно).
Рис. 1. Изображение наложенных структур ЯМР (фиолетовый) и РСА (желтый).
На самом деле структуры наложились местами очень хорошо (в основном на участках соответствующим β-листам), а местами имеют сильные расхождения в конформации. Так на рисунке 1 видно сильное отклонение хода α-спиралей в разных экспериментах. Более того есть участки, которые по разному определяются 2-ые сруктуры (рис. 2 демонстрирует участок где в модели РСА находится β-лист, а в моделях ЯМР этот же участок является петлей).
Рис. 2. Различия ЯМР и РСА моделей в определении 2-ой структуры.
Помимо всего этого удалось увидеть:
Рис. 3. Демонстрация TRP 27 в РСА и TRP 31 в ЯМР, которые различаются во всех моделях, с двумя соседями в кристалле для РСА модели.
Рис. 4. Демонстрация ARG 86 в РСА или 90 в ЯМР и GLU 83 или 87 в РСА и ЯМР моделях соответственно.
import prody
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
nmr_5zpv = prody.parsePDB('5zpv')
pca_5zf2 = prody.parsePDB('5zf2')
nmr_5zpv_prot = nmr_5zpv.select('protein').toAtomGroup()
pca_5zf2_prot = pca_5zf2.select('protein').toAtomGroup()
mean_betas = pd.DataFrame(columns = ['Residue', 'Mean_Beta'])
for res in pca_5zf2_prot.iterResidues():
if "CA" in res.getNames():
beta = np.mean(res.getBetas())
mean_betas.loc[str(res.getResnum())] = [res.getResname(), beta]
mean_betas
mean_RMSF = pd.DataFrame(columns = ['Residue', 'Mean_RMSF'])
for res in nmr_5zpv_prot.iterResidues():
if "CA" in res.getNames():
rmsf = np.mean(prody.calcRMSF(res))
mean_RMSF.loc[str(res.getResnum())] = [res.getResname(), rmsf]
mean_RMSF
mean_RMSF.iloc[3:106, 1]
fig, ax = plt.subplots()
ax.scatter(mean_betas['Mean_Beta'], mean_RMSF.iloc[3:106, 1], s=3)
ax.set_xlabel('Mean B-factor')
ax.set_ylabel('Mean RMSF')
fig.show()
Рис. 5. График зависимости B-фактора от RMSF.
Из-за одинаковой интерпретации B-фактора и RMSF, как мера подвижности (в данном случае аминокислоты), было бы логично предположить, что с увеличением первого увеличивается и второй. Однако, на полученном мной графике такая зависимость прослеживается довольно слабо. Более того просматриваются интересные выбросы с большим RMSF и достаточно низким B-фактором. Хотя если откинуть верхний левый угол графика, то зависимость будет просматриваться более ясно. Видимо это вызвано шумом в данных и неидеальностью эксперимента.
Водородная связь между атомами остова в ядре белка (в альфа-спирали или бета-листе). Здесь я выбрал ILE 76 O и VAL 21 N. В модели РСА длина такой водородной связи составляет 2.8 Å. В моделях ЯМР аминокислоты имеют номера 80 и 25.
Водородную связь боковых цепей в ядре белка. Белок у меня довольно маленький, а аминокислоты, которые не находятся на поверхности в подавляющем большинстве гидрофобные, а малая доля гидрофильных не имеет в РСА модели соседей способных образовать с ними водородные связи. Однако я нашел аминокислоты из разных вторичных структур, образующих водородную связь. Это LYS 54 NZ и GLU 35 OE1 (из β-листа и α-спирали оответственно). В модели РСА длина такой водородной связи составляет 3.5 Å.
Водородную связь в петлях, выходящих на поверхность глобулы (неважно, какие атомы, остова или боковой цепи). Здесь я выбрал SER 92 N и GLU 90 OE1. В модели РСА длина такой водородной связи составляет 2.8 Å.
dist1 = []
O1 = nmr_5zpv_prot.select('resnum 80 and name O').toAtomGroup()
N1 = nmr_5zpv_prot.select('resnum 25 and name N').toAtomGroup()
for i, j in zip(O1.iterCoordsets(), N1.iterCoordsets()):
dist1.append(float(prody.calcDistance(i, j)))
dist1
a = len(list(filter(lambda x: x <= 3.5, dist1)))
dist2_1 = []
dist2_2 = []
NZ = nmr_5zpv_prot.select('resnum 58 and name NZ').toAtomGroup()
OE1 = nmr_5zpv_prot.select('resnum 39 and name OE1').toAtomGroup()
OE2 = nmr_5zpv_prot.select('resnum 39 and name OE2').toAtomGroup()
for i, j in zip(OE1.iterCoordsets(), NZ.iterCoordsets()):
dist2_1.append(float(prody.calcDistance(i, j)))
for i, j in zip(OE2.iterCoordsets(), NZ.iterCoordsets()):
dist2_2.append(float(prody.calcDistance(i, j)))
dist2 = [min(i,j) for i,j in zip(dist2_1, dist2_2)] # учитываем, что OE1 и OE2 идентичны
b = len(list(filter(lambda x: x <= 3.5, dist2)))
dist3_1 = []
dist3_2 = []
N = nmr_5zpv_prot.select('resnum 96 and name N').toAtomGroup()
OE1 = nmr_5zpv_prot.select('resnum 94 and name OE1').toAtomGroup()
OE2 = nmr_5zpv_prot.select('resnum 94 and name OE2').toAtomGroup()
for i, j in zip(OE1.iterCoordsets(), N.iterCoordsets()):
dist3_1.append(float(prody.calcDistance(i, j)))
for i, j in zip(OE2.iterCoordsets(), N.iterCoordsets()):
dist3_2.append(float(prody.calcDistance(i, j)))
dist3 = [min(i,j) for i,j in zip(dist3_1, dist3_2)] # учитываем, что OE1 и OE2 идентичны
c = len(list(filter(lambda x: x <= 3.5, dist3)))
df = pd.DataFrame(columns = ['dist X-ray, Å', 'num_in_NMR', '%_in_NMR', 'min_dist_NMR, Å', 'max_dist_NMR, Å', 'mean_dist_NMR, Å'])
df.loc['ILE 80 O и VAL 25 N', 'dist X-ray, Å'] = 2.8
df.loc['ILE 80 O и VAL 25 N', 'num_in_NMR'] = a
df.loc['ILE 80 O и VAL 25 N', '%_in_NMR'] = a/10*100
df.loc['ILE 80 O и VAL 25 N', 'min_dist_NMR, Å'] = np.round(np.min(dist1), 2)
df.loc['ILE 80 O и VAL 25 N', 'max_dist_NMR, Å'] = np.round(np.max(dist1), 2)
df.loc['ILE 80 O и VAL 25 N', 'mean_dist_NMR, Å'] = np.round(np.median(dist1), 2)
df.loc['LYS 58 NZ и GLU 39 O', 'dist X-ray, Å'] = 3.5
df.loc['LYS 58 NZ и GLU 39 O', 'num_in_NMR'] = b
df.loc['LYS 58 NZ и GLU 39 O', '%_in_NMR'] = b/10*100
df.loc['LYS 58 NZ и GLU 39 O', 'min_dist_NMR, Å'] = np.round(np.min(dist2), 2)
df.loc['LYS 58 NZ и GLU 39 O', 'max_dist_NMR, Å'] = np.round(np.max(dist2), 2)
df.loc['LYS 58 NZ и GLU 39 O', 'mean_dist_NMR, Å'] = np.round(np.median(dist2), 2)
df.loc['SER 96 N и GLU 94 O', 'dist X-ray, Å'] = 2.8
df.loc['SER 96 N и GLU 94 O', 'num_in_NMR'] = c
df.loc['SER 96 N и GLU 94 O', '%_in_NMR'] = c/10*100
df.loc['SER 96 N и GLU 94 O', 'min_dist_NMR, Å'] = np.round(np.min(dist3), 2)
df.loc['SER 96 N и GLU 94 O', 'max_dist_NMR, Å'] = np.round(np.max(dist3), 2)
df.loc['SER 96 N и GLU 94 O', 'mean_dist_NMR, Å'] = np.round(np.median(dist3), 2)
df
Рис. 6. Водородная связь между ILE 76 O и VAL 21 N РСА модели.
Рис. 7. Водородная связь между LYS 54 NZ и GLU 35 OE1 РСА модели.
Рис. 8. Водородная связь между SER 92 N и GLU 90 OE1 РСА модели.
Исходя из данных в табличке получилось, что выбранные мною водородные связи не сохранились в ЯМР моделях. Если для остатков находящихся в петлях или близко к поверхности это вполне могло быть ожидаемо, то для β-листа это довольно странно.