aldepyde 0.0.0a2__py3-none-any.whl → 0.0.0a33__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of aldepyde might be problematic. Click here for more details.
- aldepyde/Parsers/_mmcif_parser.py +0 -0
- aldepyde/Parsers/_pdb_parser.py +0 -0
- aldepyde/__init__.py +27 -2
- aldepyde/_config.py +98 -36
- aldepyde/biomolecule/Residue.py +9 -0
- aldepyde/biomolecule/_Atom.py +95 -0
- aldepyde/biomolecule/_AtomFactory.py +71 -0
- aldepyde/biomolecule/__init__.py +18 -0
- aldepyde/biomolecule/_amino_acid.py +6 -0
- aldepyde/biomolecule/_dna.py +6 -0
- aldepyde/biomolecule/_pdb.py +455 -0
- aldepyde/biomolecule/_rna.py +6 -0
- aldepyde/biomolecule/utils.py +60 -0
- aldepyde/cache/__init__.py +2 -0
- aldepyde/cache/_cache.py +257 -0
- aldepyde/cache/cachemanager.py +212 -0
- aldepyde/cache/downloader.py +13 -0
- aldepyde/cache/utils.py +32 -0
- aldepyde/configurable.py +7 -0
- aldepyde/data/RemoteFileHandler.py +32 -0
- aldepyde/data/__init__.py +1 -0
- aldepyde/data.py +148 -0
- aldepyde/databases/PDB.py +0 -0
- aldepyde/databases/RemoteFileHandler.py +43 -0
- aldepyde/databases/UniRef.py +113 -0
- aldepyde/databases/__init__.py +0 -0
- aldepyde/databases/_database.py +41 -0
- aldepyde/env.py +43 -0
- aldepyde/fetcher/__init__.py +0 -0
- aldepyde/fetcher/test.py +2 -0
- aldepyde/json/CHG.json +25 -0
- aldepyde/json/Swiss_Prot.json +25 -0
- aldepyde/json/chemistry.json +4622 -0
- aldepyde/rand/RandomProtein.py +404 -0
- aldepyde/rand/__init__.py +6 -0
- aldepyde/stats/ProteinStats.py +89 -0
- aldepyde/stats/__init__.py +0 -0
- aldepyde/utils.py +275 -0
- {aldepyde-0.0.0a2.dist-info → aldepyde-0.0.0a33.dist-info}/METADATA +4 -3
- aldepyde-0.0.0a33.dist-info/RECORD +43 -0
- {aldepyde-0.0.0a2.dist-info → aldepyde-0.0.0a33.dist-info}/WHEEL +1 -1
- aldepyde-0.0.0a2.dist-info/RECORD +0 -7
- {aldepyde-0.0.0a2.dist-info → aldepyde-0.0.0a33.dist-info/licenses}/LICENSE +0 -0
- {aldepyde-0.0.0a2.dist-info → aldepyde-0.0.0a33.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
# Submodule for reading, writing, and fetching PDB/mmcif files
|
|
2
|
+
from aldepyde.configurable import Configurable
|
|
3
|
+
from aldepyde.data import RemoteFileHandler
|
|
4
|
+
from ._AtomFactory import *
|
|
5
|
+
from ._Atom import Atom
|
|
6
|
+
from aldepyde import cache
|
|
7
|
+
from enum import Enum
|
|
8
|
+
import urllib.request
|
|
9
|
+
import requests
|
|
10
|
+
import gzip
|
|
11
|
+
from io import BytesIO
|
|
12
|
+
import os
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
|
|
15
|
+
__all__ = ['PDB']
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
#TODO Basically rewrite this whole thing
|
|
19
|
+
class PDB(Configurable):
|
|
20
|
+
class Mode(Enum):
|
|
21
|
+
AUTO = 0
|
|
22
|
+
PDB = 1
|
|
23
|
+
CIF = 2
|
|
24
|
+
|
|
25
|
+
def __init__(self):
|
|
26
|
+
self._current = BytesIO()
|
|
27
|
+
self._mode = self.Mode.AUTO
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def SetCurrent(self, stream: BytesIO) -> None:
|
|
31
|
+
self._current = stream
|
|
32
|
+
|
|
33
|
+
def Get(self) -> BytesIO:
|
|
34
|
+
return self._current
|
|
35
|
+
|
|
36
|
+
def ToString(self) -> str:
|
|
37
|
+
return self._current.read().decode()
|
|
38
|
+
|
|
39
|
+
def clear(self) -> 'PDB':
|
|
40
|
+
return self.Clear()
|
|
41
|
+
|
|
42
|
+
def Clear(self) -> 'PDB':
|
|
43
|
+
self._current = BytesIO()
|
|
44
|
+
return self
|
|
45
|
+
|
|
46
|
+
def auto(self):
|
|
47
|
+
self._mode = self.Mode.AUTO
|
|
48
|
+
|
|
49
|
+
def pdb(self):
|
|
50
|
+
self._mode = self.Mode.PDB
|
|
51
|
+
|
|
52
|
+
def cif(self):
|
|
53
|
+
self._mode = self.Mode.CIF
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def UpdateSettings(self):
|
|
57
|
+
pass
|
|
58
|
+
|
|
59
|
+
# Enabling bad behavior
|
|
60
|
+
def fetch(self, code: str, extension: str="mmCIF") -> 'PDB':
|
|
61
|
+
return self.Fetch(code, extension=extension)
|
|
62
|
+
|
|
63
|
+
# Fetches a file directly from the PDB
|
|
64
|
+
def Fetch(self, code: str, extension: str="mmCIF") -> 'PDB':
|
|
65
|
+
code = code.lower().strip()
|
|
66
|
+
if "pdb" in extension.lower():
|
|
67
|
+
filepath = f"pdb/{code[1:3]}/pdb{code}.ent.gz"
|
|
68
|
+
name = f"pdb{code}.ent.gz"
|
|
69
|
+
else:
|
|
70
|
+
filepath = f"mmCIF/{code[1:3]}/{code}.cif.gz"
|
|
71
|
+
name = f"{code}.cif.gz"
|
|
72
|
+
fetch_url = f"https://files.rcsb.org/pub/pdb/data/structures/divided/{filepath}"
|
|
73
|
+
# stream = cache.grab_url(fetch_url, name)
|
|
74
|
+
stream = RemoteFileHandler.fetch_file_from_pdb(fetch_url, name) # TODO Why is this only a tar file on first download?
|
|
75
|
+
if RemoteFileHandler.is_gzip(stream):
|
|
76
|
+
stream = RemoteFileHandler.unpack_tar_gz_bio(stream)
|
|
77
|
+
# print(stream.getvalue())
|
|
78
|
+
self.SetCurrent(stream)
|
|
79
|
+
return self
|
|
80
|
+
|
|
81
|
+
def Load(self, file: str) -> 'PDB':
|
|
82
|
+
if file.endswith(".gz"):
|
|
83
|
+
with gzip.open(file, "r") as gz:
|
|
84
|
+
stream = BytesIO(gz.read())
|
|
85
|
+
else:
|
|
86
|
+
with open(file, "rb") as fp:
|
|
87
|
+
stream = BytesIO()
|
|
88
|
+
stream.write(fp.read())
|
|
89
|
+
self.SetCurrent(stream)
|
|
90
|
+
return self
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
#Currently only works for PDB files
|
|
94
|
+
# Fetches a file from the PDB or cache and saves it to a location
|
|
95
|
+
def SaveFetch(self, code: str, path: str, extension: str="mmCIF") -> bool:
|
|
96
|
+
stream = self.Fetch(code, extension, save=False).Get()
|
|
97
|
+
try:
|
|
98
|
+
with open(path, "wb") as fp:
|
|
99
|
+
fp.write(stream.read())
|
|
100
|
+
except:
|
|
101
|
+
return False
|
|
102
|
+
|
|
103
|
+
def Construct(self, data: str|None = None):
|
|
104
|
+
if os.path.exists(data):
|
|
105
|
+
pass
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
# TODO Everything below here :)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
# This function does too much.
|
|
113
|
+
def Read(self, file: str|BytesIO):
|
|
114
|
+
# Whatever we have, convert it to a list of string-lines
|
|
115
|
+
if isinstance(file, str) and len(file) == 4: # We have a code
|
|
116
|
+
lines = self.Fetch(file, extension='pdb', as_string=True).split('\n')
|
|
117
|
+
elif isinstance(file, str): # We have a stringline
|
|
118
|
+
pass
|
|
119
|
+
elif isinstance(file, str) and os.path.exists(file): # Path to a file
|
|
120
|
+
# Get file type
|
|
121
|
+
# Read accordingly
|
|
122
|
+
pass
|
|
123
|
+
elif isinstance(file, BytesIO): # File stream
|
|
124
|
+
pass
|
|
125
|
+
else:
|
|
126
|
+
raise ValueError("Data to read must be a PDB 4-letter code, a file as a string, a path to a file,"
|
|
127
|
+
"or a fetched file.")
|
|
128
|
+
for line in lines:
|
|
129
|
+
if line[0:6] == "ATOM " or line[0:6] == "HETATM":
|
|
130
|
+
print(line)
|
|
131
|
+
atom = self._parse_atom_pdb(line)
|
|
132
|
+
print(atom)
|
|
133
|
+
# print(lines)
|
|
134
|
+
|
|
135
|
+
def ParsePDB(self, lines):
|
|
136
|
+
for line in lines:
|
|
137
|
+
if line[0:6] == "ATOM " or line[0:6] == "HETATM":
|
|
138
|
+
print(line)
|
|
139
|
+
atom = self._parse_atom_pdb(line)
|
|
140
|
+
print(atom)
|
|
141
|
+
|
|
142
|
+
def ParseCIF(self):
|
|
143
|
+
pass
|
|
144
|
+
|
|
145
|
+
# I guess people may want this?
|
|
146
|
+
def ParseXML(self):
|
|
147
|
+
pass
|
|
148
|
+
|
|
149
|
+
def _prepare_file(self, file: str|BytesIO) -> list:
|
|
150
|
+
if isinstance(file, str):
|
|
151
|
+
file = file.strip()
|
|
152
|
+
if isinstance(file, str) and len(file) == 4: # Try reading as a pdb code
|
|
153
|
+
lines = self.Fetch(file, extension='pdb', as_string=True).split('\n')
|
|
154
|
+
elif isinstance(file, str) and os.path.exists(file): # Path to a file
|
|
155
|
+
lines = self.Load(file).split('\n')
|
|
156
|
+
elif isinstance(file, str): # We have a stringline
|
|
157
|
+
lines = file.split('\n')
|
|
158
|
+
elif isinstance(file, BytesIO): # File stream
|
|
159
|
+
lines = file.read().decode().split('\n')
|
|
160
|
+
else:
|
|
161
|
+
raise ValueError("Unable to process file.")
|
|
162
|
+
return lines
|
|
163
|
+
|
|
164
|
+
def _parse_atom_cif(self, line: str) -> Atom:
|
|
165
|
+
pass
|
|
166
|
+
|
|
167
|
+
def _parse_atom_pdb(self, line: str) -> Atom:
|
|
168
|
+
record_name = line[0:6]
|
|
169
|
+
serial = line[6:11]
|
|
170
|
+
name = line[12:16]
|
|
171
|
+
altLoc = line[16]
|
|
172
|
+
resName = line[17:20]
|
|
173
|
+
chainID = line[21]
|
|
174
|
+
resSeq = line[22:26]
|
|
175
|
+
iCode = line[26]
|
|
176
|
+
x = line[30:38]
|
|
177
|
+
y = line[38:46]
|
|
178
|
+
z = line[46:54]
|
|
179
|
+
occupancy = line[54:60]
|
|
180
|
+
tempFactor = line[60:66]
|
|
181
|
+
element = line[76:78]
|
|
182
|
+
charge = line[78:80]
|
|
183
|
+
return AtomFactory.EnforcedAtom(
|
|
184
|
+
record_name=record_name,
|
|
185
|
+
serial=serial,
|
|
186
|
+
name=name,
|
|
187
|
+
altLoc=altLoc,
|
|
188
|
+
resName=resName,
|
|
189
|
+
chainID=chainID,
|
|
190
|
+
resSeq=resSeq,
|
|
191
|
+
iCode=iCode,
|
|
192
|
+
x=x,
|
|
193
|
+
y=y,
|
|
194
|
+
z=z,
|
|
195
|
+
occupancy=occupancy,
|
|
196
|
+
tempFactor=tempFactor,
|
|
197
|
+
element=element,
|
|
198
|
+
charge=charge
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
# Surprisingly hard to design this because of how irregular PDB files are
|
|
202
|
+
# @classmethod
|
|
203
|
+
# def DetectFiletype(cls, file: str|BytesIO, trust_extension: bool = True) -> list:
|
|
204
|
+
# if isinstance(file, str) and os.path.exists(file):
|
|
205
|
+
# if trust_extension and len(Path(file).suffixes) != 0:
|
|
206
|
+
# return Path(file).suffixes
|
|
207
|
+
# extensions = []
|
|
208
|
+
# lines = cls._prepare_file(file)
|
|
209
|
+
#
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
# @classmethod
|
|
213
|
+
# def IsPDB(cls, file: str|BytesIO):
|
|
214
|
+
# pass
|
|
215
|
+
# Extrapolate file type
|
|
216
|
+
# Go line by line
|
|
217
|
+
# Grab symmetry information
|
|
218
|
+
# Parse atom information Organize residues
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
# urllib.request.urlretrieve(fetch_url, name)
|
|
222
|
+
# response = requests.get(fetch_url)
|
|
223
|
+
# response.raise_for_status()
|
|
224
|
+
# with gzip.GzipFile(fileobj=BytesIO(response.content)) as gz:
|
|
225
|
+
# with TextIOWrapper(gz) as fp:
|
|
226
|
+
# for line in fp.readlines():
|
|
227
|
+
# print(line.strip())
|
|
228
|
+
# break
|
|
229
|
+
|
|
230
|
+
# print("Fetching ", prot)
|
|
231
|
+
# import urllib.request
|
|
232
|
+
# url = r'https://files.rcsb.org/download/' + prot.strip() + '.pdb'
|
|
233
|
+
# try:
|
|
234
|
+
# with urllib.request.urlopen(url) as f:
|
|
235
|
+
# self.biomolecule.SetFetch(f.read().decode('utf-8'))
|
|
236
|
+
# self._Parse(hold_pdb)
|
|
237
|
+
# return True
|
|
238
|
+
# except urllib.error.URLError:
|
|
239
|
+
# sys.stderr.write("The requested pdb code could not be retrieved or does not exist\n")
|
|
240
|
+
# if crash:
|
|
241
|
+
# exit()
|
|
242
|
+
# return False
|
|
243
|
+
|
|
244
|
+
# def Fetch(self, code: str, extension: str="pdb"):
|
|
245
|
+
#
|
|
246
|
+
# fetch_url = r"https://files.rcsb.org/pub/pdb/data/structures/divided/pdb/b8/"
|
|
247
|
+
#
|
|
248
|
+
# url = r"https://www.rcsb.org/fasta/entry/" + prot.strip().upper() + r"/display"
|
|
249
|
+
# try:
|
|
250
|
+
# with urllib.request.urlopen(url) as f:
|
|
251
|
+
# return f.read().decode('utf-8')
|
|
252
|
+
# except urllib.error.URLError:
|
|
253
|
+
# sys.stderr.write("The requested pdb code could not be retrieved or does not exist\n")
|
|
254
|
+
# return False
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
# class PDB:
|
|
258
|
+
# def __init__(self):
|
|
259
|
+
# self.biomolecule = biomolecule()
|
|
260
|
+
# # print(apalib.j_data.GetJson())
|
|
261
|
+
#
|
|
262
|
+
# def Current(self):
|
|
263
|
+
# return self.biomolecule
|
|
264
|
+
#
|
|
265
|
+
# def FetchFASTA(self, prot):
|
|
266
|
+
# import urllib.request
|
|
267
|
+
# url = r"https://www.rcsb.org/fasta/entry/" + prot.strip().upper() + r"/display"
|
|
268
|
+
# try:
|
|
269
|
+
# with urllib.request.urlopen(url) as f:
|
|
270
|
+
# return f.read().decode('utf-8')
|
|
271
|
+
# except urllib.error.URLError:
|
|
272
|
+
# sys.stderr.write("The requested pdb code could not be retrieved or does not exist\n")
|
|
273
|
+
# return False
|
|
274
|
+
#
|
|
275
|
+
# # def FetchAsFile(self, prot):
|
|
276
|
+
# # import urllib.request
|
|
277
|
+
# # url = r'https://files.rcsb.org/download/' + prot.strip() + '.pdb'
|
|
278
|
+
# # try:
|
|
279
|
+
# # with urllib.request.urlopen(url) as f:
|
|
280
|
+
#
|
|
281
|
+
# #Enabling bad behavior
|
|
282
|
+
# def fetch(self, prot, crash=True, hold_pdb=False):
|
|
283
|
+
# return self.Fetch(prot, crash, hold_pdb)
|
|
284
|
+
# def Fetch(self, prot, crash = True, hold_pdb=False):
|
|
285
|
+
# # print("Fetching ", prot)
|
|
286
|
+
# import urllib.request
|
|
287
|
+
# url = r'https://files.rcsb.org/download/' + prot.strip() + '.pdb'
|
|
288
|
+
# try:
|
|
289
|
+
# with urllib.request.urlopen(url) as f:
|
|
290
|
+
# self.biomolecule.SetFetch(f.read().decode('utf-8'))
|
|
291
|
+
# self._Parse(hold_pdb)
|
|
292
|
+
# return True
|
|
293
|
+
# except urllib.error.URLError:
|
|
294
|
+
# sys.stderr.write("The requested pdb code could not be retrieved or does not exist\n")
|
|
295
|
+
# if crash:
|
|
296
|
+
# exit()
|
|
297
|
+
# return False
|
|
298
|
+
#
|
|
299
|
+
# def Read(self, path, hold_pdb=False):
|
|
300
|
+
# with open(path, 'r') as fp:
|
|
301
|
+
# self.biomolecule.SetFetch(fp.read())
|
|
302
|
+
# self._Parse(hold_pdb)
|
|
303
|
+
#
|
|
304
|
+
# # Wrapper for the ParsePDB file to allow functionality with a fetched protein
|
|
305
|
+
# def _Parse(self, hold_pdb=False):
|
|
306
|
+
# try:
|
|
307
|
+
# if self.biomolecule.GetFetch() is None:
|
|
308
|
+
# raise apaExcept.NoFetchError
|
|
309
|
+
# return self._ParsePDB(self.biomolecule.GetFetch(), hold_pdb)
|
|
310
|
+
# # return self._ParsePDB(self.container.GetFetch().splitlines())
|
|
311
|
+
# except apaExcept.NoFetchError as e:
|
|
312
|
+
# sys.stderr.write(e.message)
|
|
313
|
+
#
|
|
314
|
+
#
|
|
315
|
+
# #PDB standard described here: https://www.wwpdb.org/documentation/file-format-content/format33/v3.3.html
|
|
316
|
+
# def _ParsePDB(self, raw_pdb, hold_pdb=False):
|
|
317
|
+
# self.biomolecule.ClearAll()
|
|
318
|
+
# remark350 = ""
|
|
319
|
+
# if hold_pdb:
|
|
320
|
+
# self.biomolecule.SetFetch(raw_pdb)
|
|
321
|
+
# for line in raw_pdb.splitlines():
|
|
322
|
+
# # print(line)
|
|
323
|
+
# if line[0:6] == 'ATOM ' or line[0:6] == 'HETATM':
|
|
324
|
+
# self._ExtractAtomAndResidue(line)
|
|
325
|
+
# if line.find("REMARK 350") != -1:
|
|
326
|
+
# remark350 += line + "\n"
|
|
327
|
+
#
|
|
328
|
+
# symmetry_groups = self._ParseRemark350(remark350)
|
|
329
|
+
# self.biomolecule._AddSymmetry(symmetry_groups)
|
|
330
|
+
# self.biomolecule._PostParseEvaluations()
|
|
331
|
+
# def _ParseRemark350(self, remark350):
|
|
332
|
+
# lines = remark350.splitlines()
|
|
333
|
+
# lines.append("END")
|
|
334
|
+
# symFlag = False
|
|
335
|
+
# biomolecules = []
|
|
336
|
+
# for line in lines:
|
|
337
|
+
# if 'REMARK 350 APPLY' in line and ":" in line and symFlag is False:
|
|
338
|
+
# symFlag = True
|
|
339
|
+
# symLines = []
|
|
340
|
+
# chains = line[line.find(":")+1:].replace(",", " ").split()
|
|
341
|
+
# elif 'REMARK 350 APPLY' in line and ":" in line and symFlag is True:
|
|
342
|
+
# chains += line[line.find(":")+1:].replace(",", " ").split() #This feels dangerous
|
|
343
|
+
# elif 'AND CHAINS:' in line and symFlag is True:
|
|
344
|
+
# chains += line[line.find(":") + 1:].replace(",", " ").split() #This also feels dangerous
|
|
345
|
+
# elif 'BIOMT' in line and symFlag:
|
|
346
|
+
# BIOMT = line[13:19].strip()
|
|
347
|
+
# id = line[19:23].strip()
|
|
348
|
+
# x = line[23:33].strip()
|
|
349
|
+
# y = line[33:43].strip()
|
|
350
|
+
# z = line[43:53].strip()
|
|
351
|
+
# m = line[53:].strip()
|
|
352
|
+
# symLines.append([BIOMT, int(id), float(x), float(y), float(z) ,float(m)])
|
|
353
|
+
# elif symFlag:
|
|
354
|
+
# symFlag = False
|
|
355
|
+
# biomolecule = {}
|
|
356
|
+
# biomolecule['chains'] = chains
|
|
357
|
+
# for sl in symLines:
|
|
358
|
+
# if sl[1] not in biomolecule.keys():
|
|
359
|
+
# biomolecule[sl[1]] = []
|
|
360
|
+
# biomolecule[sl[1]].append([sl[0]] + sl[2:])
|
|
361
|
+
# biomolecules.append(biomolecule)
|
|
362
|
+
# #I hate PDB file format
|
|
363
|
+
# for i in range(len(biomolecules)):
|
|
364
|
+
# biomolecule = biomolecules[i]
|
|
365
|
+
# for key in biomolecule.keys():
|
|
366
|
+
# biomolecule[key].sort(key=lambda x:x[0])
|
|
367
|
+
# for i in range(len(biomolecule[key])):
|
|
368
|
+
# if key == "chains":
|
|
369
|
+
# continue
|
|
370
|
+
# biomolecule[key][i].pop(0)
|
|
371
|
+
# return biomolecules
|
|
372
|
+
#
|
|
373
|
+
# def _ExtractAtomAndResidue(self, line):
|
|
374
|
+
# serial = line[6:11].strip()
|
|
375
|
+
# name = line[12:16].strip()
|
|
376
|
+
# altLoc = line[16].strip()
|
|
377
|
+
# resName = line[17:20].strip()
|
|
378
|
+
# chainID = line[21].strip()
|
|
379
|
+
# resSeq = line[22:26].strip()
|
|
380
|
+
# iCode = line[26].strip()
|
|
381
|
+
# x = line[30:38].strip()
|
|
382
|
+
# y = line[38:46].strip()
|
|
383
|
+
# z = line[46:54].strip()
|
|
384
|
+
# occupancy = line[54:60].strip()
|
|
385
|
+
# tempFactor = line[60:66].strip()
|
|
386
|
+
# element = line[76:78].strip()
|
|
387
|
+
# charge = line[78:80].strip()
|
|
388
|
+
# atom = Atom.Atom(serial=serial, name=name, altLoc=altLoc, resName=resName, chainID=chainID, resSeq=resSeq,
|
|
389
|
+
# iCode=iCode, x=float(x), y=float(y), z=float(z), occupancy=occupancy, tempFactor=tempFactor, element=element,
|
|
390
|
+
# charge=charge)
|
|
391
|
+
# if "HETATM" in line:
|
|
392
|
+
# resType = "HETATM"
|
|
393
|
+
# else:
|
|
394
|
+
# resType = self.DetermineResType(resName)
|
|
395
|
+
# residue = self.biomolecule.AddResidue(resType, resSeq, resName, chainID)
|
|
396
|
+
# residue.InsertAtom(atom)
|
|
397
|
+
#
|
|
398
|
+
# def DetermineResType(self, res_code):
|
|
399
|
+
# if data.ValidateRNA(res_code):
|
|
400
|
+
# return 'RNA'
|
|
401
|
+
# elif data.ValidateDNA(res_code):
|
|
402
|
+
# return 'DNA'
|
|
403
|
+
# elif data.ValidateAA(res_code):
|
|
404
|
+
# return "AA"
|
|
405
|
+
# else:
|
|
406
|
+
# return "HETATM"
|
|
407
|
+
#
|
|
408
|
+
# #Remove all of the waters from the current fetch. Probably make this more general for any HETATM group. Make a wrapper?
|
|
409
|
+
# def RemoveWater(self):
|
|
410
|
+
# h_chains = self.biomolecule.GetHETATMChains()
|
|
411
|
+
# for chain in h_chains.keys():
|
|
412
|
+
# h_chains[chain] = {key: value for (key, value) in h_chains[chain].items() if value.GetResName().upper() != 'HOH'}
|
|
413
|
+
#
|
|
414
|
+
# # def Validate(self, **kwargs):
|
|
415
|
+
# # for key in kwargs:
|
|
416
|
+
# # if key != 'pdb' or (key == 'pdb' and not isinstance(kwargs['pdb'], str)):
|
|
417
|
+
# # raise apalib.apalibExceptions.BadKwarg('pdb=<pdb_to_validate>')
|
|
418
|
+
#
|
|
419
|
+
# #Write contents to a PDB file
|
|
420
|
+
#
|
|
421
|
+
# def AddChain(self, collection, name=None):
|
|
422
|
+
# if name is None:
|
|
423
|
+
# chains = list(self.biomolecule.Chains.keys())
|
|
424
|
+
# for i in range(26):
|
|
425
|
+
# if chr(ord('z') - i) not in chains:
|
|
426
|
+
# name = chr(ord('z') - i)
|
|
427
|
+
# break
|
|
428
|
+
# else:
|
|
429
|
+
# if len(name) > 1 or not name.isalnum():
|
|
430
|
+
# raise BadNameException("A chain must be a single-character alphanumeric input")
|
|
431
|
+
# #Rechain all of the atoms and residues with new name
|
|
432
|
+
# for residue in collection:
|
|
433
|
+
# residue.SetChainID(name)
|
|
434
|
+
# for atom in residue.GetAtoms():
|
|
435
|
+
# atom.SetChainID(name)
|
|
436
|
+
# self.biomolecule.AddChain(name)
|
|
437
|
+
# self.biomolecule.Chains[name] = collection
|
|
438
|
+
#
|
|
439
|
+
# def WritePDB(self, fp):
|
|
440
|
+
# s = sorted(self.biomolecule.DumpResidues(), key=lambda x: x.seqNum)
|
|
441
|
+
# with open(fp, "w") as f:
|
|
442
|
+
# for res in s:
|
|
443
|
+
# f.write(res.WriteForPDB())
|
|
444
|
+
#
|
|
445
|
+
# #Write contents to FASTA
|
|
446
|
+
# def ToFASTA(self):
|
|
447
|
+
# ls = self.biomolecule.AsList(ordered=True)
|
|
448
|
+
# retStr = ""
|
|
449
|
+
# for r in ls:
|
|
450
|
+
# if data.ValidateAA(r.resName):
|
|
451
|
+
# name = data.Map("Amino Acids", r.resName)
|
|
452
|
+
# retStr += data.GetJson()["Amino Acids"][name]["1code"]
|
|
453
|
+
# elif r.resName.upper() != "HOH":
|
|
454
|
+
# retStr += "X"
|
|
455
|
+
# return retStr
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
from ._dna import dna
|
|
2
|
+
from ._rna import rna
|
|
3
|
+
from ._amino_acid import amino_acid
|
|
4
|
+
from .Residue import Residue
|
|
5
|
+
|
|
6
|
+
# These three could probably be condensed
|
|
7
|
+
def CheckDNA(self, value: str, *args) -> bool:
|
|
8
|
+
if args == ():
|
|
9
|
+
args = self._dna_map[1]
|
|
10
|
+
map = self.load_values(*args, store_as=None)
|
|
11
|
+
if value in map['dna'].keys():
|
|
12
|
+
return True
|
|
13
|
+
return False
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def CheckRNA(self, value: str, *args) -> bool:
|
|
17
|
+
if args == ():
|
|
18
|
+
args = self._map[1]
|
|
19
|
+
map = self.load_values(*args, store_as=None)
|
|
20
|
+
if value in map['dna'].keys():
|
|
21
|
+
return True
|
|
22
|
+
return False
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def CheckAA(self, value: str, *args) -> bool:
|
|
26
|
+
if args == ():
|
|
27
|
+
args = self._map[1]
|
|
28
|
+
map = self.load_values(*args, store_as=None)
|
|
29
|
+
if value in map['dna'].keys():
|
|
30
|
+
return True
|
|
31
|
+
return False
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def CheckResidue(self, value: str, *args) -> bool:
|
|
35
|
+
if args == ():
|
|
36
|
+
args = self._map[1]
|
|
37
|
+
if self.CheckAA(value, *args):
|
|
38
|
+
return True
|
|
39
|
+
if self.CheckDNA(value, *args):
|
|
40
|
+
return True
|
|
41
|
+
if self.CheckRNA(value, *args):
|
|
42
|
+
return True
|
|
43
|
+
return False
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
# This method determines if something is DNA, RNA, or an amino acid.
|
|
47
|
+
# Don't be cheeky with this. If you aren't following the IUPAC naming schemes,
|
|
48
|
+
# you're gonna have a bad time.
|
|
49
|
+
#
|
|
50
|
+
# RNA has exclusively 1-letter codes: A, C, T, G, etc.
|
|
51
|
+
# DNA has exclusively 2-letter codes: DA, DC, DT, DG, etc.
|
|
52
|
+
# Amino acids have exclusively 3-letter codes
|
|
53
|
+
def ExtrapolateResidueType(self, value: str) -> object:
|
|
54
|
+
if self.CheckRNA(value):
|
|
55
|
+
return rna
|
|
56
|
+
if self.CheckDNA(value):
|
|
57
|
+
return dna
|
|
58
|
+
if self.CheckAA(value):
|
|
59
|
+
return amino_acid
|
|
60
|
+
return Residue
|