stcrpy 1.0.0__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.
- examples/__init__.py +0 -0
- examples/egnn.py +425 -0
- stcrpy/__init__.py +5 -0
- stcrpy/tcr_datasets/__init__.py +0 -0
- stcrpy/tcr_datasets/tcr_graph_dataset.py +499 -0
- stcrpy/tcr_datasets/tcr_selector.py +0 -0
- stcrpy/tcr_datasets/tcr_structure_dataset.py +0 -0
- stcrpy/tcr_datasets/utils.py +350 -0
- stcrpy/tcr_formats/__init__.py +0 -0
- stcrpy/tcr_formats/tcr_formats.py +114 -0
- stcrpy/tcr_formats/tcr_haddock.py +556 -0
- stcrpy/tcr_geometry/TCRCoM.py +350 -0
- stcrpy/tcr_geometry/TCRCoM_LICENCE +168 -0
- stcrpy/tcr_geometry/TCRDock.py +261 -0
- stcrpy/tcr_geometry/TCRGeom.py +450 -0
- stcrpy/tcr_geometry/TCRGeomFiltering.py +273 -0
- stcrpy/tcr_geometry/__init__.py +0 -0
- stcrpy/tcr_geometry/reference_data/__init__.py +0 -0
- stcrpy/tcr_geometry/reference_data/dock_reference_1_imgt_numbered.pdb +6549 -0
- stcrpy/tcr_geometry/reference_data/dock_reference_2_imgt_numbered.pdb +6495 -0
- stcrpy/tcr_geometry/reference_data/reference_A.pdb +31 -0
- stcrpy/tcr_geometry/reference_data/reference_B.pdb +31 -0
- stcrpy/tcr_geometry/reference_data/reference_D.pdb +31 -0
- stcrpy/tcr_geometry/reference_data/reference_G.pdb +31 -0
- stcrpy/tcr_geometry/reference_data/reference_data.py +104 -0
- stcrpy/tcr_interactions/PLIPParser.py +147 -0
- stcrpy/tcr_interactions/TCRInteractionProfiler.py +433 -0
- stcrpy/tcr_interactions/TCRpMHC_PLIP_Model_Parser.py +133 -0
- stcrpy/tcr_interactions/__init__.py +0 -0
- stcrpy/tcr_interactions/utils.py +170 -0
- stcrpy/tcr_methods/__init__.py +0 -0
- stcrpy/tcr_methods/tcr_batch_operations.py +223 -0
- stcrpy/tcr_methods/tcr_methods.py +150 -0
- stcrpy/tcr_methods/tcr_reformatting.py +18 -0
- stcrpy/tcr_metrics/__init__.py +2 -0
- stcrpy/tcr_metrics/constants.py +39 -0
- stcrpy/tcr_metrics/tcr_interface_rmsd.py +237 -0
- stcrpy/tcr_metrics/tcr_rmsd.py +179 -0
- stcrpy/tcr_ml/__init__.py +0 -0
- stcrpy/tcr_ml/geometry_predictor.py +3 -0
- stcrpy/tcr_processing/AGchain.py +89 -0
- stcrpy/tcr_processing/Chemical_components.py +48915 -0
- stcrpy/tcr_processing/Entity.py +301 -0
- stcrpy/tcr_processing/Fragment.py +58 -0
- stcrpy/tcr_processing/Holder.py +24 -0
- stcrpy/tcr_processing/MHC.py +449 -0
- stcrpy/tcr_processing/MHCchain.py +149 -0
- stcrpy/tcr_processing/Model.py +37 -0
- stcrpy/tcr_processing/Select.py +145 -0
- stcrpy/tcr_processing/TCR.py +532 -0
- stcrpy/tcr_processing/TCRIO.py +47 -0
- stcrpy/tcr_processing/TCRParser.py +1230 -0
- stcrpy/tcr_processing/TCRStructure.py +148 -0
- stcrpy/tcr_processing/TCRchain.py +160 -0
- stcrpy/tcr_processing/__init__.py +3 -0
- stcrpy/tcr_processing/annotate.py +480 -0
- stcrpy/tcr_processing/utils/__init__.py +0 -0
- stcrpy/tcr_processing/utils/common.py +67 -0
- stcrpy/tcr_processing/utils/constants.py +367 -0
- stcrpy/tcr_processing/utils/region_definitions.py +782 -0
- stcrpy/utils/__init__.py +0 -0
- stcrpy/utils/error_stream.py +12 -0
- stcrpy-1.0.0.dist-info/METADATA +173 -0
- stcrpy-1.0.0.dist-info/RECORD +68 -0
- stcrpy-1.0.0.dist-info/WHEEL +5 -0
- stcrpy-1.0.0.dist-info/licenses/LICENCE +28 -0
- stcrpy-1.0.0.dist-info/licenses/stcrpy/tcr_geometry/TCRCoM_LICENCE +168 -0
- stcrpy-1.0.0.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Created on 30 Apr 2016
|
|
3
|
+
|
|
4
|
+
@author: leem, based on work by dunbar
|
|
5
|
+
|
|
6
|
+
The MHC class. This is similar to the Fab class.
|
|
7
|
+
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from .Entity import Entity
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class MHC(Entity):
|
|
14
|
+
"""
|
|
15
|
+
MHC class.
|
|
16
|
+
Holds paired MHC domains.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def __init__(self, c1, c2):
|
|
20
|
+
if hasattr(c1, "chain_type"):
|
|
21
|
+
Entity.__init__(self, c1.id + c2.id)
|
|
22
|
+
else:
|
|
23
|
+
Entity.__init__(self, c2.id + c1.id)
|
|
24
|
+
|
|
25
|
+
self.level = "H"
|
|
26
|
+
self._add_domain(c1)
|
|
27
|
+
self._add_domain(c2)
|
|
28
|
+
self._set_MHC_type()
|
|
29
|
+
self.child_list = sorted(self.child_list, key=lambda x: x.id)
|
|
30
|
+
self.antigen = []
|
|
31
|
+
self.tcr = []
|
|
32
|
+
self.engineered = False
|
|
33
|
+
|
|
34
|
+
def _add_antigen(self, antigen=None):
|
|
35
|
+
if antigen not in self.antigen:
|
|
36
|
+
self.antigen.append(antigen)
|
|
37
|
+
|
|
38
|
+
def _add_tcr(self, tcr=None):
|
|
39
|
+
self.tcr.append(tcr)
|
|
40
|
+
|
|
41
|
+
def get_TCR(self):
|
|
42
|
+
return self.tcr
|
|
43
|
+
|
|
44
|
+
def get_antigen(self):
|
|
45
|
+
"""
|
|
46
|
+
Return a list of bound antigens.
|
|
47
|
+
If the antigen has more than one chain, those in contact with the antibody will be returned.
|
|
48
|
+
"""
|
|
49
|
+
return self.antigen
|
|
50
|
+
|
|
51
|
+
def is_bound(self):
|
|
52
|
+
"""
|
|
53
|
+
Check whether there is an antigen bound to the antibody fab
|
|
54
|
+
"""
|
|
55
|
+
if self.get_antigen():
|
|
56
|
+
return True
|
|
57
|
+
else:
|
|
58
|
+
return False
|
|
59
|
+
|
|
60
|
+
def get_chains(self):
|
|
61
|
+
for c in self:
|
|
62
|
+
yield c
|
|
63
|
+
|
|
64
|
+
def get_residues(self):
|
|
65
|
+
for c in self.get_chains():
|
|
66
|
+
for r in c:
|
|
67
|
+
yield r
|
|
68
|
+
|
|
69
|
+
def get_atoms(self):
|
|
70
|
+
for r in self.get_residues():
|
|
71
|
+
for a in r:
|
|
72
|
+
yield a
|
|
73
|
+
|
|
74
|
+
def get_MHC_type(self):
|
|
75
|
+
if hasattr(self, "MHC_type"):
|
|
76
|
+
return self.MHC_type
|
|
77
|
+
|
|
78
|
+
def get_allele_assignments(self):
|
|
79
|
+
return {c.id: c.get_allele_assignments() for c in self.get_chains()}
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class MH1(MHC):
|
|
83
|
+
"""
|
|
84
|
+
Type 1 MHC class.
|
|
85
|
+
Holds paired MHC domains.
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
def __repr__(self):
|
|
89
|
+
if self.MHC_type == "MH1":
|
|
90
|
+
return "<%s %s%s GA1/GA2=%s; B2M=%s>" % (
|
|
91
|
+
self.MHC_type,
|
|
92
|
+
self.MH1,
|
|
93
|
+
self.B2M,
|
|
94
|
+
self.MH1,
|
|
95
|
+
self.B2M,
|
|
96
|
+
)
|
|
97
|
+
else:
|
|
98
|
+
return "<GA1/GA2 %s%s GA1=%s; GA2=%s>" % (
|
|
99
|
+
self.GA1,
|
|
100
|
+
self.GA2,
|
|
101
|
+
self.GA1,
|
|
102
|
+
self.GA2,
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
def _set_MHC_type(self):
|
|
106
|
+
if hasattr(self, "MH1"):
|
|
107
|
+
self.MHC_type = "MH1"
|
|
108
|
+
elif hasattr(self, "GA1") or hasattr(self, "GA2"):
|
|
109
|
+
self.MHC_type = "MH1"
|
|
110
|
+
else:
|
|
111
|
+
self.MHC_type = ""
|
|
112
|
+
|
|
113
|
+
def _add_domain(self, chain):
|
|
114
|
+
if chain.chain_type == "MH1":
|
|
115
|
+
self.MH1 = chain.id
|
|
116
|
+
self.GA1 = chain.id
|
|
117
|
+
self.GA2 = chain.id
|
|
118
|
+
elif chain.chain_type == "GA1":
|
|
119
|
+
self.MH1 = chain.id
|
|
120
|
+
self.GA1 = chain.id
|
|
121
|
+
elif chain.chain_type == "GA2":
|
|
122
|
+
self.MH1 = chain.id
|
|
123
|
+
self.GA2 = chain.id
|
|
124
|
+
elif chain.chain_type == "B2M":
|
|
125
|
+
self.B2M = chain.id
|
|
126
|
+
|
|
127
|
+
# Add the chain as a child of this entity.
|
|
128
|
+
self.add(chain)
|
|
129
|
+
|
|
130
|
+
def get_alpha(self):
|
|
131
|
+
for MH1_domain in set(["MH1", "GA1", "GA2"]):
|
|
132
|
+
if hasattr(self, MH1_domain):
|
|
133
|
+
return self.child_dict[getattr(self, MH1_domain)]
|
|
134
|
+
|
|
135
|
+
def get_MH1(self):
|
|
136
|
+
if hasattr(self, "MH1"):
|
|
137
|
+
return self.child_dict[self.MH1]
|
|
138
|
+
|
|
139
|
+
def get_GA1(self):
|
|
140
|
+
if hasattr(self, "GA1"):
|
|
141
|
+
return self.child_dict[self.GA1]
|
|
142
|
+
else:
|
|
143
|
+
return self.get_MH1()
|
|
144
|
+
|
|
145
|
+
def get_GA2(self):
|
|
146
|
+
if hasattr(self, "GA2"):
|
|
147
|
+
return self.child_dict[self.GA2]
|
|
148
|
+
else:
|
|
149
|
+
return self.get_MH1()
|
|
150
|
+
|
|
151
|
+
def get_B2M(self):
|
|
152
|
+
if hasattr(self, "B2M"):
|
|
153
|
+
return self.child_dict[self.B2M]
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
class MH2(MHC):
|
|
157
|
+
"""
|
|
158
|
+
Type 2 MHC class.
|
|
159
|
+
Holds paired MHC domains.
|
|
160
|
+
"""
|
|
161
|
+
|
|
162
|
+
def __repr__(self):
|
|
163
|
+
if self.MHC_type == "MH2":
|
|
164
|
+
return "<%s %s%s GA=%s; GB=%s>" % (
|
|
165
|
+
self.MHC_type,
|
|
166
|
+
self.GA,
|
|
167
|
+
self.GB,
|
|
168
|
+
self.GA,
|
|
169
|
+
self.GB,
|
|
170
|
+
)
|
|
171
|
+
else:
|
|
172
|
+
return "<GA/GB %s%s GA=%s; GB=%s>" % (self.GA, self.GB, self.GA, self.GB)
|
|
173
|
+
|
|
174
|
+
def _set_MHC_type(self):
|
|
175
|
+
if hasattr(self, "GA") and hasattr(self, "GB"):
|
|
176
|
+
self.MHC_type = "MH2"
|
|
177
|
+
else:
|
|
178
|
+
self.MHC_type = ""
|
|
179
|
+
|
|
180
|
+
def _add_domain(self, chain):
|
|
181
|
+
if chain.chain_type == "GA":
|
|
182
|
+
self.GA = chain.id
|
|
183
|
+
elif chain.chain_type == "GB":
|
|
184
|
+
self.GB = chain.id
|
|
185
|
+
|
|
186
|
+
# Add the chain as a child of this entity.
|
|
187
|
+
self.add(chain)
|
|
188
|
+
|
|
189
|
+
def get_GA(self):
|
|
190
|
+
if hasattr(self, "GA"):
|
|
191
|
+
return self.child_dict[self.GA]
|
|
192
|
+
|
|
193
|
+
def get_GB(self):
|
|
194
|
+
if hasattr(self, "GB"):
|
|
195
|
+
return self.child_dict[self.GB]
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
class CD1(MHC):
|
|
199
|
+
"""
|
|
200
|
+
CD1 class.
|
|
201
|
+
Holds paired CD1/B2M domains.
|
|
202
|
+
"""
|
|
203
|
+
|
|
204
|
+
def __repr__(self):
|
|
205
|
+
if self.MHC_type == "CD1":
|
|
206
|
+
return "<%s %s%s GA1L/GA2L=%s; B2M=%s>" % (
|
|
207
|
+
self.MHC_type,
|
|
208
|
+
self.CD1,
|
|
209
|
+
self.B2M,
|
|
210
|
+
self.CD1,
|
|
211
|
+
self.B2M,
|
|
212
|
+
)
|
|
213
|
+
else:
|
|
214
|
+
return "<GA1L/GA2L %s%s GA1L=%s; GA2L=%s>" % (
|
|
215
|
+
self.GA1L,
|
|
216
|
+
self.GA2L,
|
|
217
|
+
self.GA1L,
|
|
218
|
+
self.GA2L,
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
def _set_MHC_type(self):
|
|
222
|
+
if hasattr(self, "CD1"):
|
|
223
|
+
self.MHC_type = "CD1"
|
|
224
|
+
elif hasattr(self, "GA1L") and hasattr(self, "GA2L"):
|
|
225
|
+
self.MHC_type = "CD1"
|
|
226
|
+
elif hasattr(self, "GA1L") and hasattr(self, "B2M"):
|
|
227
|
+
self.MHC_type = "CD1"
|
|
228
|
+
else:
|
|
229
|
+
self.MHC_type = ""
|
|
230
|
+
|
|
231
|
+
def _add_domain(self, chain):
|
|
232
|
+
if chain.chain_type == "CD1":
|
|
233
|
+
self.MHC_type = "CD1"
|
|
234
|
+
self.CD1 = chain.id
|
|
235
|
+
self.GA1L = chain.id
|
|
236
|
+
self.GA2L = chain.id
|
|
237
|
+
elif chain.chain_type == "GA1L":
|
|
238
|
+
self.CD1 = chain.id
|
|
239
|
+
self.GA1L = chain.id
|
|
240
|
+
elif chain.chain_type == "GA2L":
|
|
241
|
+
self.GA2L = chain.id
|
|
242
|
+
elif chain.chain_type == "B2M":
|
|
243
|
+
self.B2M = chain.id
|
|
244
|
+
|
|
245
|
+
# Add the chain as a child of this entity.
|
|
246
|
+
self.add(chain)
|
|
247
|
+
|
|
248
|
+
def get_CD1(self):
|
|
249
|
+
if hasattr(self, "CD1"):
|
|
250
|
+
return self.child_dict[self.CD1]
|
|
251
|
+
|
|
252
|
+
def get_B2M(self):
|
|
253
|
+
if hasattr(self, "B2M"):
|
|
254
|
+
return self.child_dict[self.B2M]
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
class MR1(MHC):
|
|
258
|
+
"""
|
|
259
|
+
MR1 class.
|
|
260
|
+
Holds paired MR1/B2M domains.
|
|
261
|
+
"""
|
|
262
|
+
|
|
263
|
+
def __repr__(self):
|
|
264
|
+
if self.MHC_type == "MR1":
|
|
265
|
+
return "<%s %s%s GA1L/GA2L=%s; B2M=%s>" % (
|
|
266
|
+
self.MHC_type,
|
|
267
|
+
self.MR1,
|
|
268
|
+
self.B2M,
|
|
269
|
+
self.MR1,
|
|
270
|
+
self.B2M,
|
|
271
|
+
)
|
|
272
|
+
else:
|
|
273
|
+
return "<GA1L/GA2L %s%s GA1L=%s; GA2L=%s>" % (
|
|
274
|
+
self.GA1L,
|
|
275
|
+
self.GA2L,
|
|
276
|
+
self.GA1L,
|
|
277
|
+
self.GA2L,
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
def _set_MHC_type(self):
|
|
281
|
+
if hasattr(self, "MR1"):
|
|
282
|
+
self.MHC_type = "MR1"
|
|
283
|
+
elif hasattr(self, "GA1L") and hasattr(self, "GA2L"):
|
|
284
|
+
self.MHC_type = "MR1"
|
|
285
|
+
else:
|
|
286
|
+
self.MHC_type = ""
|
|
287
|
+
|
|
288
|
+
def _add_domain(self, chain):
|
|
289
|
+
if chain.chain_type == "MR1":
|
|
290
|
+
self.MHC_type = "MR1"
|
|
291
|
+
self.MR1 = chain.id
|
|
292
|
+
self.GA1L = chain.id
|
|
293
|
+
self.GA2L = chain.id
|
|
294
|
+
elif chain.chain_type == "GA1L":
|
|
295
|
+
self.GA1L = chain.id
|
|
296
|
+
elif chain.chain_type == "GA2L":
|
|
297
|
+
self.GA2L = chain.id
|
|
298
|
+
elif chain.chain_type == "B2M":
|
|
299
|
+
self.B2M = chain.id
|
|
300
|
+
|
|
301
|
+
# Add the chain as a child of this entity.
|
|
302
|
+
self.add(chain)
|
|
303
|
+
|
|
304
|
+
def get_MR1(self):
|
|
305
|
+
if hasattr(self, "MR1"):
|
|
306
|
+
return self.child_dict[self.MR1]
|
|
307
|
+
|
|
308
|
+
def get_B2M(self):
|
|
309
|
+
if hasattr(self, "B2M"):
|
|
310
|
+
return self.child_dict[self.B2M]
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
class scMH1(MHC):
|
|
314
|
+
"""
|
|
315
|
+
Type 1 MHC class.
|
|
316
|
+
Holds single chain MHC domains for Class I MHC if the identiifed chain
|
|
317
|
+
is the double alpha helix, ie. MH1 without B2M, with exception for GA1.
|
|
318
|
+
"""
|
|
319
|
+
|
|
320
|
+
def __init__(self, c1):
|
|
321
|
+
assert c1.chain_type in [
|
|
322
|
+
"GA1",
|
|
323
|
+
"GA2",
|
|
324
|
+
"MH1",
|
|
325
|
+
], f"Chain {c1} with can not form a single chain MHC class I."
|
|
326
|
+
Entity.__init__(self, c1.id)
|
|
327
|
+
|
|
328
|
+
self.level = "H"
|
|
329
|
+
self._add_domain(c1)
|
|
330
|
+
self._set_MHC_type()
|
|
331
|
+
self.child_list = sorted(self.child_list, key=lambda x: x.id)
|
|
332
|
+
self.antigen = []
|
|
333
|
+
self.tcr = []
|
|
334
|
+
self.engineered = False
|
|
335
|
+
|
|
336
|
+
def __repr__(self):
|
|
337
|
+
if self.MHC_type == "MH1":
|
|
338
|
+
return "<%s %s GA1/GA2=%s>" % (
|
|
339
|
+
self.MHC_type,
|
|
340
|
+
self.MH1,
|
|
341
|
+
self.MH1,
|
|
342
|
+
)
|
|
343
|
+
else:
|
|
344
|
+
return "<GA1/GA2 %s GA1/GA2=%s>" % (
|
|
345
|
+
self.GA1,
|
|
346
|
+
self.GA1,
|
|
347
|
+
)
|
|
348
|
+
|
|
349
|
+
def _set_MHC_type(self):
|
|
350
|
+
if hasattr(self, "MH1") or hasattr(self, "GA1") or hasattr(self, "GA2"):
|
|
351
|
+
self.MHC_type = "MH1"
|
|
352
|
+
else:
|
|
353
|
+
self.MHC_type = ""
|
|
354
|
+
|
|
355
|
+
def _add_domain(self, chain):
|
|
356
|
+
if chain.chain_type in ["MH1", "GA1", "GA2"]:
|
|
357
|
+
self.MH1 = chain.id
|
|
358
|
+
self.GA1 = chain.id
|
|
359
|
+
self.GA2 = chain.id
|
|
360
|
+
|
|
361
|
+
# Add the chain as a child of this entity.
|
|
362
|
+
self.add(chain)
|
|
363
|
+
|
|
364
|
+
def get_alpha(self):
|
|
365
|
+
for MH1_domain in set(["MH1", "GA1", "GA2"]):
|
|
366
|
+
if hasattr(self, MH1_domain):
|
|
367
|
+
return self.child_dict[getattr(self, MH1_domain)]
|
|
368
|
+
|
|
369
|
+
def get_MH1(self):
|
|
370
|
+
if hasattr(self, "MH1"):
|
|
371
|
+
return self.child_dict[self.MH1]
|
|
372
|
+
|
|
373
|
+
def get_GA1(self):
|
|
374
|
+
if hasattr(self, "GA1"):
|
|
375
|
+
return self.child_dict[self.GA1]
|
|
376
|
+
else:
|
|
377
|
+
return self.get_MH1()
|
|
378
|
+
|
|
379
|
+
def get_GA2(self):
|
|
380
|
+
if hasattr(self, "GA2"):
|
|
381
|
+
return self.child_dict[self.GA2]
|
|
382
|
+
else:
|
|
383
|
+
return self.get_MH1()
|
|
384
|
+
|
|
385
|
+
def get_B2M(self):
|
|
386
|
+
return None
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
class scCD1(MHC):
|
|
390
|
+
"""
|
|
391
|
+
Type 1 MHC class.
|
|
392
|
+
Holds single chain MHC domains of type CD1 for Class I MHC if the identiifed chain
|
|
393
|
+
is the double alpha helix, ie. CD1 without B2M.
|
|
394
|
+
"""
|
|
395
|
+
|
|
396
|
+
def __init__(self, c1):
|
|
397
|
+
assert c1.chain_type in [
|
|
398
|
+
"GA1L",
|
|
399
|
+
"CD1",
|
|
400
|
+
], f"Chain {c1} with can not form a single chain MHC class I."
|
|
401
|
+
Entity.__init__(self, c1.id)
|
|
402
|
+
|
|
403
|
+
self.level = "H"
|
|
404
|
+
self._add_domain(c1)
|
|
405
|
+
self._set_MHC_type()
|
|
406
|
+
self.child_list = sorted(self.child_list, key=lambda x: x.id)
|
|
407
|
+
self.antigen = []
|
|
408
|
+
self.tcr = []
|
|
409
|
+
self.engineered = False
|
|
410
|
+
|
|
411
|
+
def __repr__(self):
|
|
412
|
+
if self.MHC_type == "CD1":
|
|
413
|
+
return "<%s %s GA1L=%s>" % (
|
|
414
|
+
self.MHC_type,
|
|
415
|
+
self.CD1,
|
|
416
|
+
self.CD1,
|
|
417
|
+
)
|
|
418
|
+
else:
|
|
419
|
+
return "<GA1L %s GA1L=%s>" % (
|
|
420
|
+
self.GA1L,
|
|
421
|
+
self.GA1L,
|
|
422
|
+
)
|
|
423
|
+
|
|
424
|
+
def _set_MHC_type(self):
|
|
425
|
+
if hasattr(self, "CD1") or hasattr(self, "GA1L"):
|
|
426
|
+
self.MHC_type = "CD1"
|
|
427
|
+
else:
|
|
428
|
+
self.MHC_type = ""
|
|
429
|
+
|
|
430
|
+
def _add_domain(self, chain):
|
|
431
|
+
if chain.chain_type in ["CD1", "GA1L"]:
|
|
432
|
+
self.CD1 = chain.id
|
|
433
|
+
self.GA1L = chain.id
|
|
434
|
+
|
|
435
|
+
# Add the chain as a child of this entity.
|
|
436
|
+
self.add(chain)
|
|
437
|
+
|
|
438
|
+
def get_CD1(self):
|
|
439
|
+
if hasattr(self, "CD1"):
|
|
440
|
+
return self.child_dict[self.CD1]
|
|
441
|
+
|
|
442
|
+
def get_GA1L(self):
|
|
443
|
+
if hasattr(self, "GA1L"):
|
|
444
|
+
return self.child_dict[self.GA1L]
|
|
445
|
+
else:
|
|
446
|
+
return self.get_CD1()
|
|
447
|
+
|
|
448
|
+
def get_B2M(self):
|
|
449
|
+
return None
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Created on 30 Apr 2016
|
|
3
|
+
@author: leem
|
|
4
|
+
|
|
5
|
+
Based on the ABchain class from @dunbar
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from .utils.region_definitions import get_region
|
|
10
|
+
from Bio.PDB.Chain import Chain
|
|
11
|
+
from .Entity import Entity
|
|
12
|
+
from .Fragment import Fragment
|
|
13
|
+
from Bio import SeqUtils
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class MHCchain(Chain, Entity):
|
|
17
|
+
"""
|
|
18
|
+
A class to hold an MHC chain
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
def __init__(self, id):
|
|
22
|
+
Chain.__init__(self, id)
|
|
23
|
+
Entity.__init__(self, id)
|
|
24
|
+
self.level = "C"
|
|
25
|
+
self.antigen = []
|
|
26
|
+
self.unnumbered = []
|
|
27
|
+
self.sequence = {}
|
|
28
|
+
self.residue_order = {}
|
|
29
|
+
self.engineered = False
|
|
30
|
+
self.tcr = []
|
|
31
|
+
|
|
32
|
+
def __repr__(self):
|
|
33
|
+
return "<MHCchain %s type: %s>" % (self.id, self.chain_type)
|
|
34
|
+
|
|
35
|
+
def _add_antigen(self, antigen=None):
|
|
36
|
+
if antigen not in self.antigen:
|
|
37
|
+
self.antigen.append(antigen)
|
|
38
|
+
|
|
39
|
+
def _add_tcr(self, tcr):
|
|
40
|
+
self.tcr.append(tcr)
|
|
41
|
+
|
|
42
|
+
def get_TCR(self):
|
|
43
|
+
return self.tcr
|
|
44
|
+
|
|
45
|
+
def analyse(self, chain_type):
|
|
46
|
+
self.set_chain_type(chain_type)
|
|
47
|
+
# self._init_fragments()
|
|
48
|
+
self.annotate_children()
|
|
49
|
+
self.set_sequence()
|
|
50
|
+
|
|
51
|
+
def set_chain_type(self, chain_type):
|
|
52
|
+
"""
|
|
53
|
+
Set the MHC's chain type
|
|
54
|
+
"""
|
|
55
|
+
self.chain_type = chain_type
|
|
56
|
+
|
|
57
|
+
def set_engineered(self, engineered):
|
|
58
|
+
if engineered:
|
|
59
|
+
self.engineered = True
|
|
60
|
+
else:
|
|
61
|
+
self.engineered = False
|
|
62
|
+
|
|
63
|
+
def set_sequence(self):
|
|
64
|
+
i = 0
|
|
65
|
+
for residue in self:
|
|
66
|
+
if (
|
|
67
|
+
residue.get_resname().capitalize()
|
|
68
|
+
in SeqUtils.IUPACData.protein_letters_3to1
|
|
69
|
+
):
|
|
70
|
+
resname = SeqUtils.IUPACData.protein_letters_3to1[
|
|
71
|
+
residue.get_resname().capitalize()
|
|
72
|
+
] # change this to use our chemical components.
|
|
73
|
+
else:
|
|
74
|
+
# skip the residue if the code is not recognised - e.g. UNK
|
|
75
|
+
continue
|
|
76
|
+
hetflag, resseq, icode = residue.get_id()
|
|
77
|
+
self.sequence[(self.chain_type + str(resseq) + str(icode)).strip()] = (
|
|
78
|
+
resname
|
|
79
|
+
)
|
|
80
|
+
self.residue_order[(self.chain_type + str(resseq) + str(icode)).strip()] = i
|
|
81
|
+
i += 1
|
|
82
|
+
|
|
83
|
+
def add_unnumbered(self, residue):
|
|
84
|
+
self.unnumbered.append(residue.id)
|
|
85
|
+
|
|
86
|
+
def _get_region(self, residue):
|
|
87
|
+
region = ""
|
|
88
|
+
if hasattr(residue, "imgt_numbered") and residue.imgt_numbered:
|
|
89
|
+
# Call the get_region function from ..Annotate.region_definitions module
|
|
90
|
+
region = get_region((residue.id[1], residue.id[2]), residue.chain_type)
|
|
91
|
+
return region
|
|
92
|
+
return "?"
|
|
93
|
+
|
|
94
|
+
def annotate_children(self):
|
|
95
|
+
for residue in self:
|
|
96
|
+
residue.chain_type = self.chain_type
|
|
97
|
+
residue.region = self._get_region(residue)
|
|
98
|
+
for atom in residue:
|
|
99
|
+
atom.chain_type = self.chain_type
|
|
100
|
+
atom.region = residue.region
|
|
101
|
+
# if residue.region != "?":
|
|
102
|
+
# self.fragments.child_dict[residue.region].add(residue)
|
|
103
|
+
|
|
104
|
+
def _init_fragments(self):
|
|
105
|
+
self.fragments = Entity("Fragments")
|
|
106
|
+
self.fragments.set_parent(self)
|
|
107
|
+
for region in regions[self.chain_type]:
|
|
108
|
+
self.fragments.add(Fragment(region))
|
|
109
|
+
|
|
110
|
+
def is_bound(self):
|
|
111
|
+
"""
|
|
112
|
+
Check whether there is an antigen bound to the antibody chain
|
|
113
|
+
"""
|
|
114
|
+
if self.get_antigen():
|
|
115
|
+
return True
|
|
116
|
+
else:
|
|
117
|
+
return False
|
|
118
|
+
|
|
119
|
+
def get_antigen(self):
|
|
120
|
+
return self.antigen
|
|
121
|
+
|
|
122
|
+
def get_fragments(self):
|
|
123
|
+
for f in self.fragments:
|
|
124
|
+
yield f
|
|
125
|
+
|
|
126
|
+
def get_sequence(self, type=dict):
|
|
127
|
+
if not self.sequence:
|
|
128
|
+
self.set_sequence()
|
|
129
|
+
if type is dict:
|
|
130
|
+
return self.sequence
|
|
131
|
+
else:
|
|
132
|
+
ordered = sorted(
|
|
133
|
+
list(self.sequence.items()), key=lambda x: self.residue_order[x[0]]
|
|
134
|
+
)
|
|
135
|
+
if type is str:
|
|
136
|
+
return "".join([r[1] for r in ordered])
|
|
137
|
+
else:
|
|
138
|
+
return ordered
|
|
139
|
+
|
|
140
|
+
def get_unnumbered(self):
|
|
141
|
+
for r in self.unnumbered:
|
|
142
|
+
yield self.child_dict[r]
|
|
143
|
+
|
|
144
|
+
def get_chains(self): # implemented to retain interface with MHC.get_chains()
|
|
145
|
+
for c in [self]:
|
|
146
|
+
yield c
|
|
147
|
+
|
|
148
|
+
def get_allele_assignments(self):
|
|
149
|
+
return self.xtra["genetic_origin"]
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Created on 9 May 2017
|
|
3
|
+
@author: leem
|
|
4
|
+
|
|
5
|
+
Based on the ABDB.AbPDB.Model class.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import Bio
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Model(Bio.PDB.Model.Model, Bio.PDB.Entity.Entity):
|
|
12
|
+
"""
|
|
13
|
+
Override to use our Entity
|
|
14
|
+
|
|
15
|
+
@change: __getitem__ changed so that single chains can be called as well as holder object from a model.
|
|
16
|
+
e.g. s[0]["B"] and s[0]["BA"] gets the B chain and the BA tcr respectively.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def __init__(self, identifier, serial_num=None):
|
|
20
|
+
Bio.PDB.Model.Model.__init__(self, identifier, serial_num)
|
|
21
|
+
Bio.PDB.Entity.Entity.__init__(self, identifier)
|
|
22
|
+
|
|
23
|
+
def __getitem__(self, identifier):
|
|
24
|
+
"Return the child with given identifier."
|
|
25
|
+
if identifier in self.child_dict:
|
|
26
|
+
return self.child_dict[identifier]
|
|
27
|
+
else:
|
|
28
|
+
# Allow a single chain to be called from a model.
|
|
29
|
+
for child in self:
|
|
30
|
+
if (
|
|
31
|
+
child.id in self.child_dict
|
|
32
|
+
and identifier in self.child_dict[child.id].child_dict
|
|
33
|
+
):
|
|
34
|
+
return self.child_dict[child.id].child_dict[identifier]
|
|
35
|
+
raise KeyError(
|
|
36
|
+
identifier
|
|
37
|
+
) # raise error if chain belonging to identifier is not found
|