Spaces:
Sleeping
Sleeping
File size: 10,247 Bytes
c2a02c6 2d335db c2a02c6 b9d0e9c c2a02c6 64993f7 1177ad1 c2a02c6 d040a03 b9d0e9c f2540fb f5285f2 2fb933b 99b7583 b9d0e9c f5285f2 983e197 d9d6eff c2a02c6 2d335db c2a02c6 c7f7982 2d335db c2a02c6 2d335db c2a02c6 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 |
"""
This code file produces alignments between the structure and the sequence for a given protein.
"""
import math
import glob
import numpy as np
from Bio import Align
import gzip
from pathlib import Path
from Bio.Align import substitution_matrices
from Bio.PDB.Polypeptide import *
aligner = Align.PairwiseAligner()
import requests
from Bio.PDB import PDBParser, PPBuilder
from io import StringIO
def convert_non_standard_amino_acids(sequence):
"""
Convert non-standard or ambiguous amino acid codes to their closest relatives.
"""
# Define a dictionary to map non-standard codes to standard amino acids
conversion_dict = {
'B': 'D', # Aspartic Acid (D) is often used for B (Asx)
'Z': 'E', # Glutamic Acid (E) is often used for Z (Glx)
'X': 'A', # Alanine (A) is a common placeholder for unknown/ambiguous
'U': 'C', # Cysteine (C) is often used for Selenocysteine (U)
'J': 'L', # Leucine (L) is often used for J (Leu/Ile)
'O': 'K', # Lysine (K) is often used for O (Pyrrolysine)
# '*' or 'Stop' represents a stop codon; you may replace with '' to remove
'*': '',
}
# Replace non-standard codes with their closest relatives
converted_sequence = ''.join([conversion_dict.get(aa, aa) for aa in sequence])
return converted_sequence
def distance(x1, y1, z1, x2, y2, z2):
d = math.sqrt(math.pow(x2 - x1, 2) +
math.pow(y2 - y1, 2) +
math.pow(z2 - z1, 2) * 1.0)
return d
def find_distance(coordMut, coordAnnot):
if coordMut != np.NaN:
try:
dist = distance(float(coordMut[0]), float(coordMut[1]), float(coordMut[2]), float(coordAnnot[0]),
float(coordAnnot[1]), float(coordAnnot[2]))
return "%.2f" % dist
except:
ValueError
dist = 'nan'
return dist
else:
return np.NaN
def threeToOne(variant):
if variant == "ALA":
variant = "A"
elif variant == "ARG":
variant = "R"
elif variant == "VAL":
variant = "V"
elif variant == "GLU":
variant = "E"
elif variant == "PRO":
variant = "P"
elif variant == "LEU":
variant = "L"
elif variant == "GLY":
variant = "G"
elif variant == "ASN":
variant = "N"
elif variant == "SER":
variant = "S"
elif variant == "GLN":
variant = "Q"
elif variant == "THR":
variant = "T"
elif variant == "MET":
variant = "M"
elif variant == "LYS":
variant = "K"
elif variant == "ASP":
variant = "D"
elif variant == "ILE":
variant = "I"
elif variant == "PHE":
variant = "F"
elif variant == "TRP":
variant = "W"
elif variant == "TYR":
variant = "Y"
elif variant == "HIS":
variant = "H"
elif variant == "CYS":
variant = "C"
elif variant == 'UNK':
variant = 'X'
elif variant == 'ASX':
variant = 'O'
return (variant)
def get_coords(annot, alignments, coords, resnums_for_sasa, mode):
if mode == 1:
for alignment in alignments[0]:
alignment = (str(alignment).strip().split('\n'))
startGap = 0
if alignment[0].startswith('.'):
for k in alignment[0]:
if k == '.' or k == '-':
startGap += 1
else:
break
countGap = startGap
countResidue = 0
for j in alignment[0][startGap:]:
if j == '.' or j == '-':
countGap += 1
else:
countResidue += 1
if countResidue == float(annot):
break
countGap_pdb = 0
countResidue_pdb = 0
for m in alignment[2][0:countResidue + countGap - 1]:
if m == '.' or m == '-':
countGap_pdb += 1
posAtom = countResidue + countGap - countGap_pdb
realpdbStart = 0
for j in alignment[2]:
if j == '.' or j == '-':
realpdbStart += 1
else:
break
if (alignment[2][countResidue + countGap - 1] != '-') and (float(annot) >= float(realpdbStart) + 1):
try:
coordinates = alignments[1]
residue_numbers = alignments[2]
coordWeWant = coordinates[posAtom - 1]
residue_number_we_want = residue_numbers[posAtom - 1]
except:
IndexError
coordWeWant = 'nan'
else:
coordWeWant = 'nan'
return coordWeWant, posAtom, residue_number_we_want
if mode == 2:
if annot != 'nan':
if int(annot) <= 1400:
alignment = (str(alignments).strip().split('\n'))
startGap = 0
if alignment[0].startswith('.'):
for k in alignment[0]:
if k == '.' or k == '-':
startGap += 1
else:
break
countGap = startGap
countResidue = 0
for j in alignment[0][startGap:]:
if j == '.' or j == '-':
countGap += 1
else:
countResidue += 1
if countResidue == float(annot):
break
countGap_pdb = 0
countResidue_pdb = 0
for m in alignment[2][0:countResidue + countGap - 1]:
if m == '.' or m == '-':
countGap_pdb += 1
posAtom = countResidue + countGap - countGap_pdb
realpdbStart = 0
for j in alignment[2]:
if j == '.' or j == '-':
realpdbStart += 1
else:
break
if len(alignment[2]) > (countResidue + countGap - 1):
if (alignment[2][countResidue + countGap - 1] != '-') and (float(annot) >= float(realpdbStart) + 1):
try:
coordinates = coords
residue_numbers = resnums_for_sasa
coordWeWant = coordinates[posAtom - 1]
residue_number_we_want = residue_numbers[posAtom - 1]
except:
IndexError
coordWeWant = 'nan'
residue_number_we_want = 'nan'
else:
coordWeWant = 'nan'
residue_number_we_want = 'nan'
return coordWeWant, posAtom, residue_number_we_want
else:
coordWeWant = 'nan'
residue_number_we_want = 'nan'
return coordWeWant, posAtom, residue_number_we_want
else:
return np.NaN, np.NaN, np.NaN
else:
return np.NaN, np.NaN, np.NaN
def get_alignments_3D(identifier, model_num, pdb_path, pdbSequence, source, chain, pdbID, mode, path_3D_alignment,file_format = 'gzip'):
pdbSequence = convert_non_standard_amino_acids(pdbSequence)
if mode == 1:
if source == 'PDB':
# Step 1: Fetch the PDB file
pdb_url = f"https://files.rcsb.org/download/{pdbID}.pdb"
response = requests.get(pdb_url)
response.raise_for_status() # Check for a successful response
# Step 2: Parse the PDB file from memory
atoms = [i for i in response.text.split('\n') if i.startswith('ATOM')]
atoms = [i.split() for i in atoms]
atoms = [i for i in atoms if (i[2] == 'CA' and i[4] == chain)]
atoms = [[x[i][-3:] if i == 3 else x[i] for i in range(len(x))] for x in atoms]
atomSequence = ''.join([threeToOne(i[3]) for i in atoms])
coords = [[i[6] ,i[7] ,i[8]] for i in atoms]
resnums_for_sasa = [i[5] for i in atoms]
elif source == 'SWISSMODEL':
atomSequence = ''
coords = []
resnums_for_sasa = []
with open(pdb_path, encoding="utf8") as f:
for line in f.readlines():
if line[0:4].strip() == 'ATOM' and line[13:15].strip() == 'CA' and line[21].upper() == chain.upper():
atomSequence += threeToOne(line[17:20].strip())
coords.append([line[31:38].strip(), line[39:46].strip(), line[47:54].strip()])
resnums_for_sasa.append(line[22:26].strip())
elif line[0:4].strip() == 'ATOM' and line[13:15].strip() == 'CA' and line[21] == ' ':
atomSequence += threeToOne(line[17:20].strip())
coords.append([line[31:38].strip(), line[39:46].strip(), line[47:54].strip()])
resnums_for_sasa.append(line[22:26].strip())
elif source == 'MODBASE':
atomSequence = ''
coords = []
resnums_for_sasa = []
with open(pdb_path, encoding="utf8") as f:
for line in f.readlines():
if line[0:7].strip() == 'ATOM' and line[13:15].strip() == 'CA':
atomSequence += threeToOne(line[17:20].strip())
coords.append([line[31:38].strip(), line[39:46].strip(), line[47:54].strip()])
resnums_for_sasa.append(line[22:26].strip())
aligner.mode = 'local'
aligner.substitution_matrix = substitution_matrices.load("BLOSUM62")
aligner.open_gap_score = -11
aligner.extend_gap_score = -1
atomSequence = convert_non_standard_amino_acids(atomSequence)
alignments = aligner.align(pdbSequence, atomSequence)
alignments = (list(alignments))
return alignments, coords, resnums_for_sasa
|